grails object relational mapping: gorm

108
GORM (Grails Object relational mapping) By: Saurabh Dixit

Upload: saurabh-dixit

Post on 10-May-2015

4.955 views

Category:

Technology


2 download

DESCRIPTION

GORM: All about relationships in between domain objects in Grails, and how GROM handle them

TRANSCRIPT

Page 1: Grails object relational mapping: GORM

GORM(Grails Object relational mapping)

By: Saurabh Dixit

Page 2: Grails object relational mapping: GORM

Leverages Hibernate

Automatically maps domain objects to database

Provides query and update facility1. Finding objects in persistence store(find by methods)

2. Persistence life cycle methods3. Criteria and HQL query facilities

Page 3: Grails object relational mapping: GORM

Grails injects GORM functionality into objects in run time

Declare properties for the domain class

1. The id and version properties are injected automatically.

2. All properties are not null/required by default.

Page 4: Grails object relational mapping: GORM

Associations One‐to‐one, one‐to‐many, many‐to‐

many Uni‐directional and bi‐directional Owners defined by using belongsTo property

Page 5: Grails object relational mapping: GORM

Mapping:

Many-to-one relationship: A Many-to-one relationship is the

simplest kind, and is defined with a property of the type of another domain class. Consider this example:

A unidirectional many-to-one relationship from Face to Nose:

class Face {Nose nose}

class Nose {}

Page 6: Grails object relational mapping: GORM

To make this relationship bidirectional define the other side as follows:class Face {Nose nose}class Nose {static belongsTo = [face:Face]}

Page 7: Grails object relational mapping: GORM

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 fromFace to the associated Nose:Face f = new Face()f.nose = new Nose()f.save()

Page 8: Grails object relational mapping: GORM

one-to-one Relationship: use the hasOne property on the owning

side, e.g. Face:class Author {static hasOne = [book:Book]}class Book {Author author}

Note that using this property puts the foreign key on the inverse table to the previous example, so in this case the foreign key column is stored in the nose table inside a column called face_id.

Page 9: Grails object relational mapping: GORM

hasOne only works with bidirectional relationships.

it's a good idea to add a unique constraint on one side of the one-to-one relationship:

class Author {static hasOne = [book:Book]static constraints = {

book unique: true }

}class Book {

Author author}

Page 10: Grails object relational mapping: GORM

One-to-many Relationship:class Author {static hasMany = [books: Book]String name}class Book {String title}

In this case we have a unidirectional one-to-many. Grails will, by default, map this kind of

relationship with a join table.

Page 11: Grails object relational mapping: GORM

Grails will automatically inject a property of type java.util.Set into the domain class based

on the hasMany setting. This can be used to iterate over the collection:

def a = Author.get(1)for (book in a.books) {

println book.title}

Page 12: Grails object relational mapping: GORM

The default fetch strategy used by Grails is "lazy", which means that the collection will be lazily initialized on first access.

The default cascading behaviour is to cascade saves and updates, but not deletes unless abelongsTo is also specified:

class Author {static hasMany = [books: Book]String name}class Book {static belongsTo = [author: Author]String title}

Page 13: Grails object relational mapping: GORM

If you have two properties of the same type on the many side of a one-to-many you have to use mappedBy to specify which the collection is mapped:

class Airport {static hasMany = [flights: Flight]static mappedBy = [flights: "departureAirport"]}class Flight {Airport departureAirportAirport destinationAirport}

Page 14: Grails object relational mapping: GORM

Many-to-many Relationship: Grails supports many-to-many relationships

by defining a hasMany on both sides of the relationship and having a belongsTo on the owned side of the relationship:

class Book {static belongsTo = Authorstatic hasMany = [authors:Author]String title}class Author {static hasMany = [books:Book]String name}

Page 15: Grails object relational mapping: GORM

Grails maps a many-to-many using a join table at the database level. 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.

Page 16: Grails object relational mapping: GORM

Basic Collection Types:

Relationship with the basic collection type:

As well as associations between different domain classes, GORM also supports mapping of basic collection types.

For example, the following class creates a nicknames association that is a Set of String instances:class Person {static hasMany = [nicknames: String]}

Page 17: Grails object relational mapping: GORM

GORM will map an association like the above using a join table.

You can alter various aspects of how the join table is mapped using the joinTable argument:

class Person {static hasMany = [nicknames: String]static mapping = {

hasMany joinTable: [name: 'bunch_o_nicknames',key: 'person_id',column: 'nickname',type: "text"]}

}

Page 18: Grails object relational mapping: GORM

Composition in GORM: As well as association, Grails supports the

notion of composition. In this case instead of mapping classes onto

separate tables a class can be "embedded" within the current table.

For example:class Person {

Address homeAddressAddress workAddressstatic embedded = ['homeAddress', 'workAddress']

}class Address {

String numberString code}

Page 19: Grails object relational mapping: GORM

The resulting mapping would looking like this:

If you define the Address class in a separate Groovy file in the grails-app/domain directory you will also get an address table.

Page 20: Grails object relational mapping: GORM

Custom ORM Mapping:

Custom mappings are defined using a static mapping block defined within your domain class:class Person {

…static mapping = {

version falseautoTimestamp false

}}

Page 21: Grails object relational mapping: GORM

You can also configure global mappings in Config.groovy (or an external config file) using this setting:

grails.gorm.default.mapping = {version falseautoTimestamp false

}

Page 22: Grails object relational mapping: GORM

Mapping properties:

class Person {String firstNameSting addressstatic mapping = {version falseautoTimestamp falsetable 'people' // Table namefirstName column: 'First_Name' // column nameaddress type:'text'}

}

for the type in mapping you can create user defined types using hibernate org.hibernate.usertype Interface UserType.

Page 23: Grails object relational mapping: GORM

Inheritance in GORM:

GORM supports inheritance both from abstract base classes and concrete persistent GORM entities.

Inheritance hierarchies Table‐per‐hierarchy: All classes map

to a single table Table‐per‐subclass: Each class

maps to its own table and JOINs are used

Page 24: Grails object relational mapping: GORM

For example:class Content {String author}class BlogEntry extends Content {URL url}class Book extends Content {String ISBN}class PodCast extends Content {byte[] audioStream}

In the above example we have a parent Content class and then various child classes with more specific behavior.

Page 25: Grails object relational mapping: GORM

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.), share the same table.

By default same table, for Table-per-hierarchy.

Page 26: Grails object relational mapping: GORM

Table-per-hierarchy mapping has a down side in that you cannot have non-nullable properties with inheritance mapping.

To have two different tables for them: use table-per-hierarchy=false

To use table per subclass:▪ tablePerHierarchy false

Page 27: Grails object relational mapping: GORM

Retrieving Objects: get(), getAll(), read()

Listing objects: list(), listOrderBy*() methods order, sort, offset, and max named

arguments

Page 28: Grails object relational mapping: GORM

Sets, Lists and Maps:

Sets: Sets of Objects

By default when you define a relationship with GORM it is a java.util.Set which is an unordered collection that cannot contain duplicates. In other words when you have:class Author {static hasMany = [books: Book]}

Page 29: Grails object relational mapping: GORM

The books property that GORM injects is a java.util.Set. Sets guarantee uniquenes but not order, which may not be what you want. To have custom ordering you configure the Set as a SortedSet:class Author {SortedSet booksstatic hasMany = [books: Book]}

Page 30: Grails object relational mapping: GORM

In the above case a java.util.SortedSet implementation is used which means you must implement java.lang.Comparable in your Book class:class Book implements Comparable {

String titleDate releaseDate = new Date()int compareTo(obj) {

releaseDate.compareTo(obj.releaseDate)}

}

Page 31: Grails object relational mapping: GORM

Lists of Objects: To keep objects in the order which they were

added and to be able to reference them by index like an array you can define your collection type as a List:class Author {List booksstatic hasMany = [books: Book]}

In this case when you add new elements to the books collection the order is retained in a sequential list indexed from 0 so you can do:author.books[0] // get the first book

Page 32: Grails object relational mapping: GORM

Bags of Objects: If ordering and uniqueness aren't a

concern (or if you manage these explicitly) then you can use the Hibernate Bag type to represent mapped collections.

The only change required for this is to define the collection type as a Collection:

Page 33: Grails object relational mapping: GORM

class Author {Collection booksstatic hasMany = [books: Book]

}

Since uniqueness and order aren't managed by Hibernate, adding to or removing from collections mapped as a Bag don't trigger a load of all existing instances from the database, so this approach will perform better and require less memory than using a Set or a List.

Page 34: Grails object relational mapping: GORM

Maps of Objects: If you want a simple map of string/value

pairs GORM can map this with the following:class Author {Map books // map of ISBN:book names}def a = new Author()a.books = ["1590597583":"Grails Book"]a.save()

In this case the key and value of the map MUST be strings.

Page 35: Grails object relational mapping: GORM

If you want a Map of objects then you can do this:class Book {Map authorsstatic hasMany = [authors: Author]}def a = new Author(name:"Stephen King")def book = new Book()book.authors = [stephen:a]book.save()

Page 36: Grails object relational mapping: GORM

Collection Types and Performance:

The Java Set type doesn't allow duplicates. 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.

Page 37: Grails object relational mapping: GORM

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.

Page 38: Grails object relational mapping: GORM

For example consider the following code:def book = new Book(title:"New Grails Book")def author = Author.get(1)book.author = authorbook.save()

In this example the association link is being created by the child (Book) and hence it is not necessary to manipulate the collectiodirectly resulting in fewer queries and more efficient code.

Page 39: Grails object relational mapping: GORM

Given an Author with a large number of associated Book instances if you were to write code like the following you would see an impact on performance:def book = new Book(title:"New Grails Book")def author = Author.get(1)author.addToBooks(book)author.save()

You could also model the collection as a Hibernate Bag as described above.

Page 40: Grails object relational mapping: GORM

Eager and Lazy Fetching:

By default Lazy fetching, object will be loaded only when it will be accessed.

Lazy can be set to false to enable eager fetching:class Airport {

String namestatic hasMany = [flights: Flight]static mapping = {

flights lazy: false}

}

In this case the flights association will be loaded at the same time as its Airport instance

Page 41: Grails object relational mapping: GORM

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".

Page 42: Grails object relational mapping: GORM

For example:class Airport {

String namestatic hasMany = [flights: Flight]static mapping = {

flights batchSize: 10}

}

In this case, due to the batchSize argument, when you iterate over the flights association,Hibernate will fetch results in batches of 10.

Page 43: Grails object relational mapping: GORM

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 10.

Page 44: Grails object relational mapping: GORM

In other words:batch fetching is an optimization of the lazyfetching strategy.

Batch fetching can also be configured at the class level as follows:class Flight {…static mapping = {

batchSize 10}

}

Page 45: Grails object relational mapping: GORM

Optimistic and Pessimistic Locking:

Optimistic Locking: By default GORM classes are

configured for optimistic locking. 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.

Page 46: Grails object relational mapping: GORM

The version column gets read into a version property that contains the current versioned state of persistent instance which you can access:def airport = Airport.get(10)println airport.version

When you perform updates Hibernate will automatically check the version property against the version column in the database and if they differ will throw a StaleObjectException. This will rollback the transaction if one is active.

The version will only be updated after flushing the session.

Page 47: Grails object relational mapping: GORM

Dealing with the locking through exception handling:def airport = Airport.get(10)try { airport.name = "Heathrow" airport.save(flush: true)}catch (org.springframework.dao.OptimisticLockingFailureException e) {// deal with exception}

The way you deal with the exception depends on the application. You could attempt a programmatic merge of the data or go back to the user and ask them to resolve the conflict.

Page 48: Grails object relational mapping: GORM

Pessimistic Locking: Pessimistic locking is equivalent to

doing a SQL "SELECT * FOR UPDATE" statement and locking a row in the database.

This has the implication that other read operations will be blocking until the lock is released.

Page 49: Grails object relational mapping: GORM

In Grails pessimistic locking is performed on an existing instance with the lock method:

def airport = Airport.get(10)airport.lock() // lock for updateairport.name = "Heathrow"airport.save()

Grails will automatically deal with releasing the lock for you once the transaction has been committed.

In the above case what we are doing is "upgrading" from a regular SELECT to a SELECT..FOR UPDATE and another thread could still have updated the record in between the call to get() and the call to lock().

Page 50: Grails object relational mapping: GORM

To get around this problem you can use the static lock method that takes an id just like get:def airport = Airport.lock(10) // lock for updateairport.name = "Heathrow"airport.save()

Page 51: Grails object relational mapping: GORM

Using pessimistinc locking in dynamic finders and criteria:

As well as the lock method you can also obtain a pessimistic locking using queries. For example using a dynamic finder:

def airport = Airport.findByName("Heathrow", [lock: true])

Or using criteria:

def airport = Airport.createCriteria().get {eq('name', 'Heathrow')lock true}

Page 52: Grails object relational mapping: GORM

Modification Checking:

You can use the isDirty method to check if any field has been modified:

def airport = Airport.get(10)assert !airport.isDirty()airport.properties = paramsif (airport.isDirty()) {// do something based on changed state}

isDirty() does not currently check collection associations, but it does check all other persistent properties and associations.

Page 53: Grails object relational mapping: GORM

You can also check if individual fields have been modified:

def airport = Airport.get(10)assert !airport.isDirty()airport.properties = paramsif (airport.isDirty('name')) {// do something based on changed name}

Page 54: Grails object relational mapping: GORM

getDirtyPropertyNames: You can use the

getDirtyPropertyNames method to retrieve the names of modified fields; this may be empty but will not be null:def airport = Airport.get(10)assert !airport.isDirty()airport.properties = paramsdef modifiedFieldNames = airport.getDirtyPropertyNames()for (fieldName in modifiedFieldNames) {// do something based on changed value}

Page 55: Grails object relational mapping: GORM

getPersistentValue: You can use the getPersistentValue method

to retrieve the value of a modified field:def airport = Airport.get(10)assert !airport.isDirty()airport.properties = paramsdef modifiedFieldNames = airport.getDirtyPropertyNames()for (fieldName in modifiedFieldNames) {def currentValue = airport."$fieldName"def originalValue = airport.getPersistentValue(fieldName)if (currentValue != originalValue) {// do something based on changed value

}}

Page 56: Grails object relational mapping: GORM

Dynamic finders (findBy*())

Use property names of the class Support for many expressions in

finder methoddef book = Book.findByTitle("The Stand")book = Book.findByTitleLike("Harry Pot%")

Like is comparator, due to the Like comparator, above finder is equivalent to a SQL like expression.

Page 57: Grails object relational mapping: GORM

The possible comparators include:InList In the list of given values

LessThan less than a given value

LessThanEquals

less than or equal a give value

GreaterThan greater than a given value

GreaterThanEquals

greater than or equal a given value

Like Equivalent to a SQL like expression

Ilike Similar to a Like, except case insensitive

NotEqual Negates equality

Between Between two values (requires two arguments)

IsNotNull Not a null value (doesn't take an argument)

IsNull Is a null value (doesn't take an argument)

Page 58: Grails object relational mapping: GORM

Between, IsNotNull and IsNull require different numbers of method arguments compared to the rest, as demonstrated in the following example:

def now = new Date()def lastWeek = now - 7def book =

Book.findByReleaseDateBetween(lastWeek, now)books = Book.findAllByReleaseDateIsNull()books = Book.findAllByReleaseDateIsNotNull()

Page 59: Grails object relational mapping: GORM

Boolean logic (AND/OR): Method expressions can also use a

boolean operator to combine two or more criteria:

def books = Book.findAllByTitleLikeAndReleaseDateGreaterThan(

"%Java%", new Date() - 30)

In this case we're using And in the middle of the query to make sure both conditions are satisfied, but you could equally use Or:def books =

Book.findAllByTitleLikeOrReleaseDateGreaterThan("%Java%", new Date() - 30)

Page 60: Grails object relational mapping: GORM

GORM Criteria queries:

Built on Hibernate’s Criteria API Groovy builder is used to build up the criteria

▪Hierarchy of method calls and closures for building tree‐like structures

Each domain class has a createCriteria() method▪Call get, list, scroll, or count on criteria▪ The criteria builder is used to restrict the query

Supports associations and projections

Page 61: Grails object relational mapping: GORM

Some Criteria queries:def c = Account.createCriteria()

def results = c.list {like("holderFirstName", "Fred%")and {between("balance", 500, 1000)eq("branch", "London")}maxResults(10)order("holderLastName", "desc")}

Page 62: Grails object relational mapping: GORM

Below is a node reference for each criterion method:

Node Description Example

between Where the property value is between two distinct values

between("balance", 500, 1000)

eq Where a property equals a particular value.

eq("branch", "London")

eq (caseinsensitive)

A version of eq that supports anoptional 3rd Map parameter tospecify that the query be caseinsensitive.

eq("branch", "london",[ignoreCase: true])

eqProperty Where one property must equalanother

eqProperty("lastTx", "firstTx")

Page 63: Grails object relational mapping: GORM

Node Description Example

gt Where a property is greater than a particular value

gt("balance",1000)

gtProperty

Where a one property must be greater than another

gtProperty("balance", "overdraft")

ge Where a property is greater than or equal to a particular value

ge("balance", 1000)

geProperty

Where a one property must be greater than or equal to another

geProperty("balance", "overdraft")

idEq Where an objects id equals the specified value

idEq(1)

ilike A case-insensitive 'like' expression ilike("holderFirstName", "Steph%")

in where a property is not contained within the specified list of values.Note: 'in' is a Groovy reserve word,so it must be escaped by quotes.

'in'("age",[18..65]) or not{'in'("age",[18..65])}

Page 64: Grails object relational mapping: GORM

isEmpty Where a collection property is empty

isEmpty("transactions")

isNotEmpty Where a collection property is notempty

isNotEmpty("transactions")

isNotEmpty Where a collection property is notempty

isNotEmpty("transactions")

isNull Where a property is null isNull("holderGender")

isNotNull Where a property is not null isNotNull("holderGender")

lt Where a property is less than aparticular value

lt("balance", 1000)

ltProperty Where a one property must be lessthan another

ltProperty("balance", "overdraft")

le Where a property is less than orequal to a particular value

le("balance", 1000)

leProperty Where a one property must be lessthan or equal to another

leProperty("balance", "overdraft")

Page 65: Grails object relational mapping: GORM

like Equivalent to SQL like expression like("holderFirstName","Steph%")

ne Where a property does not equal a particular value

ne("branch", "London")

neProperty

Where one property does not equal another

neProperty("lastTx", "firstTx")

order Order the results by a particular property

order("holderLastName","desc")

rlike Similar to like, but uses a regex.Only supported on Oracle and MySQL.

rlike("holderFirstName",/Steph.+/)

sizeEq Where a collection property's size equals a particular value

sizeEq("transactions", 10)

sizeGt Where a collection property's size isgreater than a particular value

sizeGt("transactions", 10)

sizeGe Where a collection property's size isgreater than or equal to a particular value

sizeGe("transactions", 10)

Page 66: Grails object relational mapping: GORM

sizeLt Where a collection property's size isless than a particular value

sizeLt("transactions", 10)

sizeLe Where a collection property's size isless than or equal to a particular value

sizeLe("transactions", 10)

sizeNe Where a collection property's size isnot equal to a particular value

sizeNe("transactions", 10)

sqlRestriction

Use arbitrary SQL to modify theresultset

sqlRestriction"char_length(first_name) = 4"

Page 67: Grails object relational mapping: GORM

With dynamic finders, you have access to options such as max, sort, etc.

These are available to criteria queries as well, but they have different names:

Name Description Example

order(String,String)

Specifies both the sort column (the first argument) and the sort order (either 'asc' or 'desc').

order "age", "desc"

firstResult(int) Specifies the offset for the results. A value of 0 will return all records up to the maximum specified.

firstResult 20

maxResults(int) Specifies the maximum number of records to return.

maxResults 10

cache(boolean) Indicates if the query should be cached (if the query cacheis enabled).

cache true

Page 68: Grails object relational mapping: GORM

Criteria also support the notion of projections.

A projection is used to change the nature of the results. For example the following query uses a projection to count the number of distinct branch names that exist for each Account:

def c = Account.createCriteria()def branchCount = c.get {projections {countDistinct "branch"}}

Page 69: Grails object relational mapping: GORM

The following table summarizes the different projections and what they do:Name Description Example

property Returns the given property in the returned results

property("firstName")

distinct Returns results using a single or collection of distinct property names

distinct("fn") ordistinct(['fn', 'ln'])

avg Returns the average value of the given property

avg("age")

count Returns the count of the given property name

count("branch")

countDistinct Returns the count of the given property name for distinct rows

countDistinct("branch")

Page 70: Grails object relational mapping: GORM

groupProperty Groups the results by the given property

groupProperty("lastName")

max Returns the maximum value of the given property

max("age")

min Returns the minimum value of the given property

min("age")

sum Returns the sum of the given property

sum("balance")

rowCount Returns count of the number of rows returned

rowCount()

Page 71: Grails object relational mapping: GORM

Criteria can be written as:def query = {and { eq('survey', survey) eq('user',user) }} FormSubmission.createCriteria().list(query) or FormSubmission.createCriteria().list{ and { eq('survey', survey) eq('user',user) }}

Page 72: Grails object relational mapping: GORM

Adding SQLRestrictions in a criteria:

Find all the users with first name, lastname dob, but their status should not be null or test_user, and their role should be ROLE_USER in userrole table.

User UserRole classes are created by springSecurityPlugin:

Page 73: Grails object relational mapping: GORM

Role userRole = Role.findByAuthority('ROLE_USER');

UserList = User.createCriteria().list{and{if(params.firstName){ilike('firstName',params.firstName+'%')}if(params.lastName){ilike('lastName', params.lastName+'%')}if(birthDate){eq('birth', birthDate)}sqlRestriction("({alias}.status IS NULL

OR CAST({alias}.status AS nvarchar) != 'test_user') AND ${userRole.id} in (Select ur.role_id from user_role ur where ur.user_id={alias}.id)")

}if (!params.offset) {params.offset = 0}if (!params.max) {params.max = 10}maxResults(params.max.toInteger())firstResult(params.offset.toInteger())}

Page 74: Grails object relational mapping: GORM

GORM: HQL

Support for Hibernate Query Language: find(hql), findAll(hql), and

executeQuery(hql) for queries executeUpdate(hql) for DML‐style

opera3ons (sets of updates or deletes) Support for positional and named

parametersEAVEntity.executeQuery("SELECT e.id FROM EAVEntity e

WHERE e.initialEntryBy=:entryFor AND e.attribute=:attrId", [entryFor:''+entryFor+'', attrId: this.parentAttribute])

Page 75: Grails object relational mapping: GORM

// simple queryAccount.executeQuery("select distinct a.number from Account

a")

// using with list of parametersAccount.executeQuery("select distinct a.number from Account

a " +"where a.branch = ? and a.created > ?",['London', lastMonth])

// using with a single parameter and pagination paramsAccount.executeQuery("select distinct a.number from Account

a " +"where a.branch = ?", ['London'], [max: 10, offset: 5])

Page 76: Grails object relational mapping: GORM

// using with a single parameter and pagination paramsAccount.executeQuery("select distinct a.number from Account a " +"where a.branch = ?", ['London'], [max: 10, offset: 5])

// using with Map of named parametersAccount.executeQuery("select distinct a.number from Account a " +"where a.branch = :branch", [branch: 'London'])

// same as previousAccount.executeQuery("select distinct a.number from Account a "+“where a.branch = :branch", [branch: 'London'], [max: 10, offset: 5])

Page 77: Grails object relational mapping: GORM

// tell underlying Hibernate Query object to not attach newly retrieved

// objects to the session, will only save with explicit saveAccount.executeQuery("select distinct a.number from Account a",null, [readOnly: true])

// time request out after 18 secondsAccount.executeQuery("select distinct a.number from Account a",null, [timeout: 18])

Page 78: Grails object relational mapping: GORM

// have Hibernate Query object return 30 rows at a timeAccount.executeQuery("select distinct a.number from Account a",

null, [fetchSize: 30])

// modify the FlushMode of the Query (default is FlushMode.AUTO)

Account.executeQuery("select distinct a.number from Account a",null, [flushMode: FlushMode.MANUAL])

Page 79: Grails object relational mapping: GORM

The executeQuery method allows the execution of arbitrary HQL queries.

HQL queries can return domain class instances, or Arrays of specified data when the query selects individual fields or calculated values.

Page 80: Grails object relational mapping: GORM

The basic syntax is: Book.executeQuery(String query)Book.executeQuery(String query, List positionalParams)Book.executeQuery(String query, List positionalParams, Map metaParams)Book.executeQuery(String query, Map namedParams)Book.executeQuery(String query, Map namedParams, Map metaParams)

query- An HQL query positionalParams - A List of parameters for a positional

parameterized query namedParams - A Map of named parameters for a named

parameterized query metaParams - A Map of pagination parameters max or/and

offset, as well as Hibernate query parameters readOnly, fetchSize, timeout, and flushMode

Page 81: Grails object relational mapping: GORM

Support for Writing native queries: Defining new SQL instance: creating a

new sql instance, basically it will create a new instance of the connection:Sql sql = Sql.newInstance(dataSource)

Then we can execute the methods on the sql.

sql.rows("SELECT id FROM eavchoice_entity_value WHERE entity_id=:id",[id:newEntityId]);

String entityInsertQuery = "insert into eaventity (version, attribute_id, initial_entry_by) VALUES (0, $attributeId, '$entryFor')";

def newEntity = sql.executeInsert(entityInsertQuery); sql.close()

Page 82: Grails object relational mapping: GORM

Using Explicit Transaction with Native sql queries:

▪ // Creating sql instanceSql sql = Sql.newInstance(dataSource)

▪ // Instantiating transaction managerDataSourceTransactionManager txm = new

DataSourceTransactionManager(dataSource)

Page 83: Grails object relational mapping: GORM

// instantiating transaction through transaction managerdef status = txm.getTransaction( new DefaultTransactionDefinition() )try{/*Write sql queries*/sql.close()txm.commit(status)}catch(Exception e){log.error("Exception in saving data", e)// Transaction roll backtxm.rollback(status)}finally(){sql.close()//Cleanup resources after transaction completion.txm.cleanupAfterCompletion( status )}

Page 84: Grails object relational mapping: GORM

Where Queries: The where method, introduced in Grails

2.0, builds on the support for Detached Criteria by providing an enhanced, compile-time checked query DSL for common queries.

The where method is more flexible than dynamic finders, less verbose than criteria and provides a powerful mechanism to compose queries.

Page 85: Grails object relational mapping: GORM

Basic Querying: The where method accepts a closure

that looks very similar to Groovy's regular collection methods.

The closure should define the logical criteria in regular Groovy syntax, for example:def query = Person.where {firstName == "Bart"}Person bart = query.find()

Page 86: Grails object relational mapping: GORM

The returned object is a DetachedCriteria instance, which means it is not associated with any particular database connection or session.

This means you can use the where method to define common queries at the class level:

class Person {static simpsons = where {lastName == "Simpson"}…}

Page 87: Grails object relational mapping: GORM

Query execution is lazy and only happens upon usage of the DetachedCriteria instance.

If you want to execute a where-style query immediately there are variations of the findAll and find methods to accomplish this:

def results = Person.findAll {lastName == "Simpson"}def results = Person.findAll(sort:"firstName") {lastName == "Simpson"}Person p = Person.find { firstName == "Bart" }

Page 88: Grails object relational mapping: GORM

Each Groovy operator maps onto a regular criteria method.

The following table provides a map of Groovy operators to methods:Operato

rCriteria Method

Description

== eq Equal to

!= ne Not Equal to

> gt Greater than

< lt Less than

>= ge Greater than or equal to

<= le Less than or equal to

in inList Contained within the given list

==~ like Like a given string

=~ ilike Case insensitive like

Page 89: Grails object relational mapping: GORM

It is possible use regular Groovy comparison operators and logic to formulate complex queries:

def query = Person.where {(lastName != "Simpson" && firstName != "Fred") || (firstName == "Bart" &&age > 9)}def results = query.list(sort:"firstName") The Groovy regex matching operators map onto like

and ilike queries unless the expression on the right hand side is a Pattern object, in which case they map onto an rlike query:def query = Person.where {

firstName ==~ ~/B.+/}

** Note that rlike queries are only supported if the underlying database supports regular expressions

Page 90: Grails object relational mapping: GORM

A between criteria query can be done by combining the in keyword with a range:

def query = Person.where {age in 18..65}

Finally, you can do isNull and isNotNull style queries by using null with regular comparison operators:

def query = Person.where {middleName == null}

Page 91: Grails object relational mapping: GORM

Query Composition: Since the return value of the where

method is a DetachedCriteria instance you can compose new queries from the original query:def query = Person.where {lastName == "Simpson"}def bartQuery = query.where {firstName == "Bart"}Person p = bartQuery.find()

Page 92: Grails object relational mapping: GORM

Note that you cannot pass a closure defined as a variable into the where method unless it has been explicitly cast to a DetachedCriteria instance.

In other words the following will produce an error:def callable = {lastName == "Simpson"}def query = Person.where(callable)

Page 93: Grails object relational mapping: GORM

The above must be written as follows:

import grails.gorm.DetachedCriteriadef callable = {lastName == "Simpson"} as DetachedCriteria<Person>def query = Person.where(callable)

As you can see the closure definition is cast (using the Groovy as keyword) to a DetachedCriteria instance targeted at the Person class.

Page 94: Grails object relational mapping: GORM

Conjunction, Disjunction and Negation: As mentioned previously you can combine

regular Groovy logical operators (|| and &&) to form conjunctions and disjunctions:

def query = Person.where {(lastName != "Simpson" && firstName != "Fred") || (firstName == "Bart" &&age > 9)}

You can also negate a logical comparison using !:

def query= Person.where {firstName == "Fred" && !(lastName == 'Simpson')}

Page 95: Grails object relational mapping: GORM

Property Comparison Queries: If you use a property name on both the

left hand and right side of a comparison expression then the appropriate property comparison criteria is automatically used:

def query = Person.where {firstName == lastName}

Page 96: Grails object relational mapping: GORM

The following table described how each comparison operator maps onto each criteria property comparison method:Operator Criteria

MethodDescription

== eqProperty Equal to

!= neProperty Not equal to

> gtProperty Greater than

< ltProperty Less than

>= geProperty Greater than or equalto

<= leProperty Less than or equal to

Page 97: Grails object relational mapping: GORM

Querying Associations: Associations can be queried by using the

dot operator to specify the property name of the

association to be queried:def query = Pet.where {owner.firstName == "Joe" || owner.firstName == "Fred"}

Page 98: Grails object relational mapping: GORM

You can group multiple criterion inside a closure method call where the name of the method matches the association name:def query = Person.where {pets { name == "Jack" || name == "Joe" }}

This technique can be combined with other top-level criteria:def query = Person.where {pets { name == "Jack" } || firstName == "Ed"}

Page 99: Grails object relational mapping: GORM

For collection associations it is possible to apply queries to the size of the collection:

def query = Person.where {pets.size() == 2}

Page 100: Grails object relational mapping: GORM

Subqueries: It is possible to execute subqueries

within where queries. For example to find all the people older than the average age the following query can be used:

final query = Person.where {age > avg(age)}

Page 101: Grails object relational mapping: GORM

The following table lists the possible subqueries:Method Description

avg The average of all values

sum The sum of all values

max The maximum value

min The minimum value

count The count of all values

property Retrieves a property of the resultingentities

Page 102: Grails object relational mapping: GORM

You can apply additional criteria to any subquery by using the of method and passing in a closure containing the criteria:def query = Person.where {age > avg(age).of { lastName == "Simpson" } && firstName ==

"Homer"}

Since the property subquery returns multiple results, the criterion used compares all results.

For example the following query will find all people younger than people with the surname "Simpson":Person.where {age < property(age).of { lastName == "Simpson" }}

Page 103: Grails object relational mapping: GORM

Other Functions:

There are several functions available to you within the context of a query. These are summarized in the table below:Method Description

second The second of a date property

minute The minute of a date property

hour The hour of a date property

day The day of the month of a date property

month The month of a date property

year The year of a date property

upper Converts a string property to upper case

lower Converts a string property to lower case

length The length of a string property

trim Trims a string property

Page 104: Grails object relational mapping: GORM

**Currently functions can only be applied to properties or associations of domain classes. You cannot, for example, use a function on a result of a subquery.

For example the following query can be used to find all pet's born in 2011:

def query = Pet.where {year(birthDate) == 2011}

You can also apply functions to associations:def query = Person.where {year(pets.birthDate) == 2009}

Page 105: Grails object relational mapping: GORM

Batch Updates and Deletes:▪ Since each where method call returns a

DetachedCriteria instance, you can use where queries to execute batch operations such as batch updates and deletes.▪ For example, the following query will update

all people with the surname "Simpson" to have the surname "Bloggs":def query = Person.where {lastName == 'Simpson'}int total = query.updateAll(lastName:"Bloggs")

Page 106: Grails object relational mapping: GORM

**Note that one limitation with regards to batch operations is that join queries (queries that query associations) are not allowed.

To batch delete records you can use the deleteAll method:

def query = Person.where {lastName == 'Simpson'}int total = query.deleteAll()

Page 107: Grails object relational mapping: GORM
Page 108: Grails object relational mapping: GORM

Thanks..