Grails Training - Developed and delivered by the folks who created and actively maintain the Grails framework!. Introduced in GORM 6. It results in less code to write, compile time optimization, and ease of testing. The guide will stay focused on the service layer of the app consistent with persistence.
|Published (Last):||13 June 2004|
|PDF File Size:||17.15 Mb|
|ePub File Size:||18.87 Mb|
|Price:||Free* [*Free Regsitration Required]|
Table of contents 1 Introduction. Table of Contents 6. ImprovedNamingStrategy import org. String name String description. Quick Reference hide. Command Line Usage. Constraints Usage. Controllers Usage. Database Mapping Usage. Domain Classes Usage.
Plug-ins Usage. Services Usage. Servlet API request. Tag Libraries Usage. Tags actionSubmit. Copies of this document may be made for your own use and for distribution to others, provided that you do not charge any fee for such copies and further provided that each copy contains this Copyright Notice, whether distributed in print or electronically.
They hold state about business processes and hopefully also implement behavior. They are linked together through relationships; one-to-one, one-to-many, or many-to-many. Under the hood it uses Hibernate 3 a very popular and flexible open source ORM solution and thanks to the dynamic nature of Groovy with its static and dynamic typing, along with the convention of Grails, there is far less configuration involved in creating Grails domain classes.
You can also write Grails domain classes in Java. See the section on Hibernate Integration for how to write domain classes in Java but still use dynamic persistent methods. Person If no package is specified with the create-domain-class script, Grails automatically uses the application name as the package name.
Note that if you explicitly call the save method then the object is placed back into a read-write state. Hibernate then initializes the proxied instance, or throws an exception if no record is found for the specified id. For example if you were building an Amazon -style bookstore you would be thinking about books, authors, customers and publishers to name a few. The next few sections show how to model the domain in GORM. To create a domain class you run the create-domain-class command as follows: grails create-domain-class org.
For example: package org. Unless specified explicitly at both ends, a relationship exists only in the direction it is defined. The result of this is that we can create a Face , attach a Nose instance to it and when we save or delete the Face instance, GORM will save or delete the Nose. In other words, saves and deletes will cascade from Face to the associated Nose : new Face nose: new Nose. Note that the inverse is not true and will result in an error due to a transient Face : new Nose face: new Face.
Also, hasOne only works with bidirectional relationships. They may even be self-referential, i. Such situations can cause problems because Grails may guess incorrectly the type of the association.
So when you set the parent property on a Person instance, Grails will automatically set the supervisor property on the other Person instance. This may be what you want, but if you look at the class, what we in fact have are two unidirectional relationships. And of course this works for normal domain classes too, not just self-referential ones. Nor is the mappedBy property limited to many-to-one and one-to-one associations: it also works for one-to-many and many-to-many associations as you'll see in the next section.
If you have a property called "none" on your domain class, this approach won't work currently! The "none" property will be treated as the reverse direction of the association or the "back reference". Fortunately, "none" is not a common domain class property name. Grails will, by default, map this kind of relationship with a join table.
The ORM DSL allows mapping unidirectional relationships using a foreign key association instead Grails will automatically inject a property of type java. Set into the domain class based on the hasMany setting. The owning side of the relationship, in this case Author , takes responsibility for persisting the relationship and is the only side that can cascade saves across.
For example this will work and cascade saves: new Author name: "Stephen King". Grails' Scaffolding feature does not currently support many-to-many relationship and hence you must write the code to manage the relationship yourself 6.
In this case instead of mapping classes onto separate tables a class can be "embedded" within the current table. Considerations At the database level Grails by default uses table-per-hierarchy mapping with a discriminator column called class so the parent class Content and its subclasses BlogEntry , Book etc. Table-per-hierarchy mapping has a down side in that you cannot have non-nullable properties with inheritance mapping.
An alternative is to use table-per-subclass which can be enabled with the ORM DSL However, excessive use of inheritance and table-per-subclass can result in poor query performance due to the use of outer join queries. In general our advice is if you're going to use inheritance, don't abuse it and don't make your inheritance hierarchy too deep. Polymorphic Queries The upshot of inheritance is that you get the ability to polymorphically query.
Set which is an unordered collection that cannot contain duplicates. Sets guarantee uniqueness but not order, which may not be what you want. SortedSet implementation is used which means you must implement java. When using a List , elements must be added to the collection before being saved, otherwise Hibernate will throw an exception org.
The keys for the map must be strings. To ensure uniqueness when adding an entry to a Set association Hibernate has to load the entire associations from the database. If you have a large numbers of entries in the association this can be costly in terms of performance. The same behavior is required for List types, since Hibernate needs to load the entire association to maintain order.
Therefore it is recommended that if you anticipate a large numbers of records in the association that you make the association bidirectional so that the link can be created on the inverse side. Grails automatically binds a Hibernate session to the currently executing request. This lets you use the save and delete methods as well as other GORM methods transparently. Transactional Write-Behind A useful feature of Hibernate over direct JDBC calls and even other frameworks is that when you call save or delete it does not necessarily perform any SQL operations at that point.
Hibernate batches up SQL statements and executes them as late as possible, often at the end of the request when flushing and closing the session. This is typically done for you automatically by Grails, which manages your Hibernate session.
Hibernate caches database updates where possible, only actually pushing the changes when it knows that a flush is required, or when a flush is triggered programmatically. One common case where Hibernate will flush cached updates is when performing queries since the cached information might be included in the query results. But as long as you're doing non-conflicting saves, updates, and deletes, they'll be batched until the session is flushed.
This can be a significant performance boost for applications that do a lot of database writes. Note that flushing is not the same as committing a transaction. If your actions are performed in the context of a transaction, flushing will execute SQL updates but the database will save the changes in its transaction queue and only finalize the updates when the transaction commits.
But there are occasions when you want to control when those statements are executed or, in Hibernate terminology, when the session is "flushed". If that validation fails the domain instance will not be persisted to the database. Just remember that when you are saving domain instances that have been bound with data provided by the user, the likelihood of validation exceptions is quite high and you won't want those exceptions propagating to the end user.
You can find out more about the subtleties of saving data in this article - a must read! A common error that may occur is if you violate a database constraint, although this is normally down to a programming or schema error. If you really need to batch delete data you can use the executeUpdate method to do batch DML statements: Customer.
The key part to remember is the belongsTo setting which controls which class "owns" a relationship. If you do not define belongsTo then no cascades will happen and you will have to manually save each object except in the case of the one-to-many, in which case saves will cascade automatically if a new instance is in a hasMany collection. To understand this better take a look at the summaries below that describe the default behaviour of GORM with regards to specific associations.
Also read part 2 of the GORM Gotchas series of articles to get a deeper understanding of relationships and cascading. You can also use fetch: 'join' instead of lazy: false , in which case GORM will only execute a single query to get the airports and their flights. This works well for single-ended associations, but you need to be careful with one-to-manys.
Queries will work as you'd expect right up to the moment you add a limit to the number of results you want. At that point, you will likely end up with fewer results than you were expecting. The reason for this is quite technical but ultimately the problem arises from GORM using a left outer join. So, the recommendation is currently to use fetch: 'join' for single-ended associations and lazy: false for one-to-manys.
Be careful how and where you use eager loading because you could load your entire database into memory with too many eager associations. Using Batch Fetching Although eager fetching is appropriate for some cases, it is not always desirable.
If you made everything eager you could quite possibly load your entire database into memory resulting in performance and memory problems.
An alternative to eager fetching is to use batch fetching. You can configure Hibernate to lazily fetch results in "batches". For example if you had an Airport that had 30 flights, if you didn't configure batch fetching you would get 1 query to fetch the Airport and then 30 queries to fetch each flight.
With batch fetching you get 1 query to fetch the Airport and 3 queries to fetch each Flight in batches of In other words, batch fetching is an optimization of the lazy fetching strategy. Optimistic locking is a feature of Hibernate which involves storing a version value in a special version column in the database that is incremented after each update.
7 Object Relational Mapping (GORM)
The canonical reference for building a production grade API with Spring. We can start without having to specify any explicit data source configuration — by default Grails uses the HSQLDB database for the development and testing environments. But if you want to change these defaults, you can define your selected data-source in the application. Grails is capable of creating the database structure for our domain classes, based on the dbCreate property in the database configuration. Note how we're specifying our validation constraints right in the model , which keeps things nice and clean, and annotation-free. These constraints will be checked by Grails automatically when the entity is being persisted and the framework will throw appropriate validation exceptions if any of these constraints are broken. Now if we call User.
GORM 7 - A powerful Groovy-based data access toolkit for the JVM
Table of contents 1 Introduction. Table of Contents 6. ImprovedNamingStrategy import org. String name String description.
6 Object Relational Mapping (GORM) - Reference Documentation
Nov 29, Beginner comments. Wouldn't it be cool if we could save information to the database by having this instead? ORM frameworks objective is to present an API where you can just think and program in objects, and the underlying framework will handle how to interface with the relational database. Create a groovy class inside the domain folder E. For example, Person. Read In case you know the primary key id of a specific row e. Update Updating an existing is as simple as calling the save method of the domain instance.