Prabin Upreti
Prabin Upreti

Reputation: 498

In GORM, Object is not modified in database when the object property is modified at Controller

In my Grails App, I have bootstrapped an object of a domain class as:

def user1 = new Users(userID: 1, name: "John Doe")
            user1.save()

In my dashboard controller i have retrieved the object and modified its property name as:

Users userObj = Users.get((Long) 1)
println(userObj as JSON); // This gives me: {"class":"com.prabin.domains.Users","id":1,"name":"John Doe"}
userObj.name = "anonymous"

Now i create a new Users object to retrieve the changed object with same ID 1 as

Users otherUserObj = Users.get((Long) 1) // **Line 2** Is this retrieving from database or from GORM session?
print(otherUserObj as JSON)// This gives me: {"class":"com.prabin.domains.Users","id":1,"name":"anonymous"}

But the value of object in database is not changed. And even when i retrieve the Users object of same id 1 in another controller it gives me the initial object rather than the modified as:

Users userObjAtDifferentController = Users.get(1);
print(userObjAtDifferentController) //This gives me: {"class":"com.prabin.domains.Users","id":1,"name":"John Doe"}

My question is, if the value is not changed in the database, why it gives me the modified object at Line 2 though i have retrieved the object using GORM query (which i guess should retrieve from the database)?

I have also tried using save() after the modification but the result is same.

userObj.save() //doesn't show the changes in database.

Upvotes: 1

Views: 611

Answers (3)

Narayan Subedi
Narayan Subedi

Reputation: 1343

You need to consider two things:

  1. If you do save(), it only retains in hibernate session, until you flush it the changes does not persist in database. So, better do save(flush:true, failOnError: true) and put in try/catch block and print exception.

  2. And another important things is, your method in controller needs to be with @Transactional annotation, without it your changes does not persist in database, you will encounter Connection is read-only. Queries leading to data modification are not allowed. exception.

Hope this helps, let me know if your issue is fixed. Happy coding . :)

Upvotes: 1

elixir
elixir

Reputation: 1442

When you call the save() method on a domain object, it may not persist in the database immediately. In order to persist the changed value to the database, you would need to do the following.

userObj.save(flush: true)

By using flush, you are telling GORM to persist immediately in the database.

In some cases when validation fails, the data will still not persist in the database. The save() method will fail silently. To catch validation errors as well as save to the database immediately, you would want to do the following

userObj.save(flush:true, failOnError:true)

If validation errors exist, then the GROM will throw ValidationException (http://docs.grails.org/latest/api/grails/validation/ValidationException.html)

Upvotes: 1

Dónal
Dónal

Reputation: 187529

My guess is that the object is not being saved to the database because some constraint(s) are invalid. You can determine whether this is the case by replacing your calls to save() with save(failOnError: true). If my guess is correct, an exception will be thrown if saving to the database fails.

Upvotes: 2

Related Questions