2015-12-09 67 views
3

我不得不使用createSQLQuery將值插入帶有使用hibernate的Identity列(第一列和主鍵)的表中。使用休眠類不是一種選擇,因爲這些表是爲添加到系統中的每個客戶實時創建的。我已經運行了查詢併成功插入到表中。然後我執行一個「select scope_identity()」,它總是返回null。 「select @@ Identity」起作用,但不能保證是正確的。我也嘗試追加「select scope_identity()」到插入查詢。然後我試圖query.list()query.uniqueResult()這兩個拋出的休眠異常「無結果...」在休眠時使用createSQLQuery選擇scope_identity()

Session session = DatabaseEngine.getSessionFactory().openSession(); 
    String queryString = "insert into table1 (dataid) values (1)" 
    SQLQuery query = session.createSQLQuery(insertQueryString); 
    query.executeUpdate(); 
    query = session.createSQLQuery("select scope_identity()"); 
    BigDecimal entryID = (BigDecimal)query.uniqueResult(); 

這個簡單的例子表的定義如下:

"CREATE TABLE table1 (EntryID int identity(1,1) NOT NULL," + 
    "DataID int default 0 NOT NULL, " + 
    "PRIMARY KEY (EntryID))"; 

有沒有辦法,我缺少使用scope_identity()與createSQLQuery

回答

1

實際上Hibernate使用的SQLServerDialect類也使用相同的「scope_identity()」。

它不工作的原因是因爲您需要在同一個語句或存儲過程中執行這些操作。 如果您在單獨的語句中執行scope_identity()調用,SQL Server將無法爲您提供上次插入的標識值。

你不能用SQLQuery這樣做,即使Hibernate使用JDBC來完成這個任務。我寫了一個測試在GitHub上仿效這一點,它的工作原理是這樣的:

Session session = entityManager.unwrap(Session.class); 
final AtomicLong resultHolder = new AtomicLong(); 
session.doWork(connection -> { 
    try(PreparedStatement statement = connection.prepareStatement("INSERT INTO post VALUES (?) select scope_identity() ")) { 
     statement.setString(1, "abc"); 
     if (!statement.execute()) { 
      while (!statement.getMoreResults() && statement.getUpdateCount() != -1) { 
       // do nothing until we hit the resultset 
      } 
     } 
     try (ResultSet rs = statement.getResultSet()) { 
      if(rs.next()) { 
       resultHolder.set(rs.getLong(1)); 
      } 
     } 
    } 
}); 
assertNotNull(resultHolder.get()); 

該代碼使用Java 8 Lambda表達式,而不是匿名類的,但你可以很容易移植到Java的1.7了。