Reputation: 35
I am new to using hibernate and grails. I have multiple java objects that I need to persist. To learn how it works I'm using a simple example of an employee class. Its in my src/java with the corresponding xml mappings with it. I think I need to make a session instance from my session factory, and I do not know what I'm doing wrong. I followed a tutorial for setting up hibternate hibernate tut and tried to translate it for grails. Any thoughts?
package com.turingpages.Matrix.view
import org.springframework.dao.DataIntegrityViolationException
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.codehaus.groovy.grails.commons.ApplicationHolder as AH
class MatrixController {
def ctx = AH.application.mainContext
def sessionFactory = ctx.sessionFactory
static allowedMethods = [save: "POST", update: "POST", delete: "POST"]
...
def create() {
def session = sessionFactory.currentSession
Transaction tx = null;
Integer employeeID = null;
try{
tx = session.beginTransaction();
Employee employee = new Employee("fname", "lname", 100);
employeeID = (Integer) session.save(employee);
tx.commit();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
return employeeID;
}
My stack trace:
ERROR errors.GrailsExceptionResolver - NullPointerException occurred when processing request: [POST] /turingpages/matrix/create
Cannot get property 'currentSession' on null object. Stacktrace follows:
Message: Cannot get property 'currentSession' on null object
Line | Method
->> 33 | create in com.turingpages.Matrix.view.MatrixController$$ENvP7skK
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 195 | doFilter in grails.plugin.cache.web.filter.PageFragmentCachingFilter
| 63 | doFilter in grails.plugin.cache.web.filter.AbstractFilter
| 1110 | runWorker in java.util.concurrent.ThreadPoolExecutor
| 603 | run . . . in java.util.concurrent.ThreadPoolExecutor$Worker
^ 722 | run in java.lang.Thread
Upvotes: 0
Views: 2260
Reputation: 35864
There's no reason you should be writing code like that with Grails. If you really need to manage the transaction in a controller, you should do it this way.
def create() {
Integer employeeID = null;
Employee.withTransaction { status ->
Employee employee = new Employee(firstName: "fname", lastName: "lname", noIdea: 100);
employee.save()
if (employee.hasErrors()) {
status.setRollbackOnly()
}
}
return employee.id;
}
That said, when dealing with a single Domain like this, you don't really need to worry about it at all:
def create() {
Employee employee = new Employee(firstName: "fname", lastName: "lname", noIdea: 100);
employee.save(flush: true)
[employee: employee] // generally you want to pass the object back to a view this way
// deal with errors in the domain on the view
}
And even better would be to use a Service class. But that can be your homework assignment.
Upvotes: 1
Reputation: 3076
You need to move the code
def ctx = AH.application.mainContext
def sessionFactory = ctx.sessionFactory
into the method create(), or replace it with
def sessionFactory
However, Grails provides a withTransaction method to serve your purpose in a simpler way:
def create() {
Employee.withTransaction{ status ->
Employee employee = new Employee("fname", "lname", 100).save()
.....
if (employee.id) {
return employee.id
}
else {
status.setRollbackOnly()
}
}
}
Upvotes: 0