在Hibernate中使用createSQLQuery选择scope_identity()

4
我被迫使用createSQLQuery来通过hibernate向具有Identity列(第一列和主键)的表中插入值。由于为每个添加到系统中的客户创建了表,因此不能使用hibernate类。我运行了查询并成功地将其插入表中。然后执行"select scope_identity()",但总是返回null。"select @@Identity"可以工作,但不能保证是正确的。我还尝试将"select scope_identity()"附加到插入查询中。然后我尝试了query.list()query.uniqueResult(),它们都抛出了hibernate异常"No Results ..."。
    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))";

有没有我忽略的方法可以在createSQLQuery中使用scope_identity()
1个回答

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。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接