2013-01-24 72 views
0

我是使用hibernate和grails的新手。我有多個我需要堅持的java對象。要了解它是如何工作的,我使用一個員工類的簡單示例。它在我的src/java中與它相應的xml映射。我想我需要從會話工廠創建一個會話實例,但我不知道我做錯了什麼。我按照教程設置了hibternate hibernate tut並試圖將它翻譯爲grails。有什麼想法嗎?Grails + hibernate +控制器sessionFactory null對象?

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; 
    } 

我的堆棧跟蹤:

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 

回答

1

您沒有理由用Grails編寫這樣的代碼。如果你真的需要在控制器中管理事務,你應該這樣做。

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; 
} 

也就是說,像這樣一個域名打交道時,你並不需要擔心它在所有:

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 
} 

更妙的是使用一個Service類。但那可以是你的家庭作業。

+0

+1,實際上'新員工(「fname」,「lname」,100)'也是錯誤的。 – coderLMN

+0

如果我使用該代碼,則會在'static matrices.Employee.withTransaction()'上得到一個無方法異常。 Employee是src/java中的一個java類,我在相同的位置有相應的XML映射。 – dagilmore

+0

這是因爲你不能將Employee更改爲grails域名,或者是因爲你認爲你不能這樣做? – Gregg

0

您需要

def ctx = AH.application.mainContext 
def sessionFactory = ctx.sessionFactory 

def sessionFactory 

但是移動代碼添加到方法創建(),或更換,Grails提供了一個withTransaction方法以更簡單的方式服務於您的目的:

def create() { 
     Employee.withTransaction{ status -> 
      Employee employee = new Employee("fname", "lname", 100).save() 
      ..... 
      if (employee.id) { 
       return employee.id 
      } 
      else { 
       status.setRollbackOnly() 
      } 
     } 
    }