2015-06-09 142 views
1

我想存儲一個對象到數據庫使用休眠,但我得到一個異常,我完全失去了原因。堅持一個對象與休眠

我已經開發了兩種方法:首先,使用保存/持續/合併方法如下:

sessionCARTIF.beginTransaction(); 
sessionCARTIF.save((Schedulers)object); 
sessionCARTIF.getTransaction().commit(); 

在這種情況下,我得到異常提交結果時拋出。它說the transaction was nos successfully started

其次,我有常見的SQL查詢嘗試如下:

String sSQL = "INSERT INTO SCHEDULERS(SCHEDULER_ID, SCHEDULER_NAME, START_DATE," 
       + "FINISH_DATE, TIMER, EVENT_ID, BUILDING_ID, EVENT_PROPERTIES)" 
       + " VALUES ("+object.getSchedulerId()+", '"+object.getSchedulerName()+"', " 
       + "to_timestamp('"+object.getStartDate()+"','YYYY-MM-DD HH24:MI:SS.FF'), " 
       + "to_timestamp('"+object.getFinishDate()+"','YYYY-MM-DD HH24:MI:SS.FF'), " 
       + " '"+object.getTimer()+"', "+object.getEvents().getEventId()+", " 
       + "'"+object.getBuildingId()+"', '"+object.getEventProps()+"');"; 
sessionCARTIF.createSQLQuery(sSQL).executeUpdate(); 

在第二種情況下,異常說org.hibernate.exception.SQLGrammarException。但是,查詢已經通過數據庫圖形界面進行了測試,並且工作正常。

任何想法??

在此先感謝

+0

你有BeginTransaction方法之前打開的會話?即sessionCARTIF.openSession(); – smoggers

+0

你的SQL查詢似乎不正確formed.just嘗試在'SYSO'中使用 – 2015-06-09 11:39:59

+0

你使用彈簧? –

回答

1

有幾個原因,你可能會收到關於未成功啓動事務的錯誤。第一個也是最常見的一個原因是您嘗試在同一個會話中執行多個事務(Hibernate會話通常是事務綁定的,當您提交會話時會關閉,除非您將auto_close_session選項更改爲false)。

通常的圖案是創建一個SessionFactory對象需要創建Session S:

public class HibernateUtil { 
    private static final SessionFactory sessionFactory; 
    static { 
    try { 
     // Create the SessionFactory from hibernate.cfg.xml 
     sessionFactory = new Configuration().configure().buildSessionFactory(); 
    } catch (Throwable ex) { 
     // Make sure you log the exception, as it might be swallowed 
     System.err.println("Initial SessionFactory creation failed." + ex); 
     throw new ExceptionInInitializerError(ex); 
    } 
    } 

    public static SessionFactory getSessionFactory() { 
    return sessionFactory; 
    } 
} 

然後使用工廠來對每一項交易創建會話,像這樣:

Session session = HibernateUtil.getSessionFactory().openSession(); 
Transaction tx = null; 
try { 
    tx = session.beginTransaction(); 
    // work with the db 
    tx.commit(); 
} 
catch (Exception e) { 
    if (tx != null) { 
    tx.rollback(); 
    } 
    // Handle the exception, print message, etc. 
} finally { 
    session.close(); 
} 

另一個出現此錯誤的原因是因爲您擁有非事務性數據源或連接定義,或者您在數據庫級啓用了自動提交功能,或者事務處於禁用狀態(某些數據庫需要特定的驅動程序或庫來支持事務處理離子,尤其是分佈式交易)。

SQL字符串產生錯誤的原因可能是由於將您連接到您的SQL字符串中的一個或多個參數的字符串轉換爲字符串所致。當你連接時,Java調用每個類的.toString()方法,並且輸出不可能是你期望的(特別是使用日期和非字符串值)。要驗證這是否是問題,請打印sSQL字符串並檢查實際正在生成的SQL並最終發佈該SQL。

請注意,將值連接成SQL指令被認爲是不好的做法,可能會導致SQL injection!最好使用PreparedStatement,並分別設置參數。這也有處理類型轉換爲你的副作用,特別是對日期,例如:

PreparedStatement stmt = conn.prepareStatement("INSERT INTO SCHEDULERS(SCHEDULER_ID, SCHEDULER_NAME, START_DATE," 
    + "FINISH_DATE, TIMER, EVENT_ID, BUILDING_ID, EVENT_PROPERTIES)" 
    + " VALUES (?, ?, ?, ?, ?, ?, ?, ?)"); 

stmt.setString(1, object.getSchedulerId()); 
stmt.setString(2, object.getSchedulerName()); 
stmt.setDate(3, object.getStartDate()); 
stmt.setDate(4, object.getFinishDate()); 
stmt.setString(5, object.getTimer()); 
stmt.setString(6, object.getEvents().getEventId()); 
stmt.setString(7, object.getBuildingId()); 
stmt.setString(8, object.getEventProps()); 

stmt.executeUpdate(); 

注意,在這種情況下,你不必採取把字串,報價照顧,不需要以處理日期格式,並且在這種情況下SQL注入保證不可能。

+0

非常感謝您的回答。如果我理解正確,你的建議是使用純java.sql,對吧?或者它是Hibernate框架的一個例子嗎?除此之外,每次我提交結果時會話都會關閉,不是嗎?因爲我的驅動程序是多線程的,所以每次都必須提交結果,因此,如果我理解得很好,每次必須與數據庫交互時都必須打開會話。 –

+0

我用示例代碼更新了我的答案,關於如何創建會話工廠以及從中實例化會話 – EmirCalabuch

+0

另外,對於查詢參數,我的建議關注純JDBC調用,但是Hibernate支持具有命名參數的類似機制:https:// docs。 jboss.org/hibernate/orm/3.2/api/org/hibernate/Query.html – EmirCalabuch