为了调查 Hibernate 的行为是否不同于 NHibernate 的 for a particular usage scenario , 我开始为基于 NHibernate 的应用程序的相关部分编写 Java SE & Hibernate 端口,但是在获取实体时遇到了问题,其中相应的 SQL Server 2008 R2 Express 表使用 uniqueidentifier
作为主键。
这是映射文件:
<!-- User.hbm.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="hibernatetest.entity.User" table="aspnet_Users">
<id name="Id">
<column name="UserId" sql-type="uniqueidentifier" not-null="true" />
</id>
<!-- ... -->
以及对应的POJO定义:
// hibernatetest/entity/User.java
package hibernatetest.entity;
import java.util.UUID;
public class User {
private UUID id;
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
//...
主要代码:
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.openSession();
User currentUser = (User) session.get(User.class, UUID.fromString("473D248D-8D91-41C9-BD73-8ACA45539D79"));
问题是对 Session#get 的调用返回 null
,因为它找不到主键的用户实体 '473D248D-8D91-41C9-BD73-8ACA45539D79'
.
当我启用完整日志记录时,我看到:
DEBUG [main] (AbstractBatcher.java:401) - select user0_.UserId as UserId0_0_ from aspnet_Users user0_ where user0_.UserId=?
Hibernate: select user0_.UserId as UserId0_0_ from aspnet_Users user0_ where user0_.UserId=?
TRACE [main] (NullableType.java:133) - binding '2c6d8085f3f2808eeae1f6e1aef5f4e9ecaed5d5c9c43c19837718ed05af828082ca808cece5e1f3f4d3e9e7c2e9f4f3ca808bedeff3f4d3e9e7c2e9f4f3f8f03df30a4ac5d31df9c7bda40d0d11c149' to parameter: 1
我不知道 Hibernate 是如何导出值 '2c6d8085f...
的,但这不是我期望的值绑定(bind),它阻止了用户实体的定位。
如果我将 hibernatetest.entity.User
的 id
字段的类型从 java.util.UUID
更改为 String
,那么这一行就成功找到了实体:
User currentUser = (User) session.get(User.class, "473D248D-8D91-41C9-BD73-8ACA45539D79");
日志输出变为:
DEBUG [main] (AbstractBatcher.java:401) - select user0_.UserId as UserId0_0_ from aspnet_Users user0_ where user0_.UserId=?
Hibernate: select user0_.UserId as UserId0_0_ from aspnet_Users user0_ where user0_.UserId=?
TRACE [main] (NullableType.java:133) - binding '473D248D-8D91-41C9-BD73-8ACA45539D79' to parameter: 1
Hibernate 如何计算值 '2c6d8085f...
以绑定(bind) UUID '473D248D-8D91-41C9-BD73-8ACA45539D79'
?我怎样才能让它绑定(bind)实际的 UUID 值?
最佳答案
Java UUID
(java.util.UUID
) 和 SQL Server uniqueidentifier
是两个不同的东西。您是在告诉 Hibernate 在两者之间进行映射。我很惊讶 Hibernate 能够做任何事情,而且它生成的内容非常奇怪,我并不感到惊讶。
据我所知(不要对 SQL Server 做太多工作)Hibernate 会将 uniqueidentifier
视为普通的旧字符串列。因此,您最好的选择可能是将其映射为一个字符串。您仍然可以将 getUUID()
和 setUUID()
作为...
public UUID getUUID() {
return UUID.fromString(id);
}
public void setUUID(UUID val) {
id = val.toString();
}
只需确保如果您正在执行基于属性的映射,那么 Hibernate 知道 UUID 字段是一个 transient 字段并且不会尝试同时存储 ID 和 UUID。
SQL Server 可能有某种特殊的 UUID 类,您可以在 Java 中使用它,它可以与 Java UUID 相互转换。也有可能一些新版本的 Hibernate 已经支持将 java.util.UUID 映射到 SQL Server 的 UUID,但我认为这两种可能性都不是真的。
编辑:在进一步调查问题后,我可以看出您的一些困惑。看起来 NHibernate 实际上确实从 System.GUID
转换为 SQL Server 的 uniqueidentifier
(这是有道理的,因为两者都是与 Microsoft 相关的)。但是,我认为没有 Hibernate 的等价物。
关于java - 使用 uniqueidentifier 主键获取实体时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4787906/