在Hibernate中使用createSQLQuery选择scope_identity()

时间:2015-12-09 23:03:17

标签: java sql-server hibernate

我被迫使用createSQLQuery使用hibernate将值插入到具有Identity列(第一列和主键)的表中。使用hibernate类不是一种选择,因为表是为添加到系统的每个客户动态创建的。我已运行查询并成功插入表中。然后我执行一个" select scope_identity()"它总是返回null。 "选择@@ Identity"有效,但不能保证是正确的。我还尝试追加"选择scope_identity()"到插入查询。然后我尝试query.list()query.uniqueResult()这两个都抛出了"没有结果的休眠异常..."

    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 个答案:

答案 0 :(得分: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 lambdas而不是匿名类,但您也可以轻松将其移植到Java 1.7。