有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

获取具有唯一标识符主键的实体时出现java问题

为了研究Hibernate的行为是否与NHibernate的for a particular usage scenario不同,我开始编写JavaSE&;我的基于NHibernate的应用程序的相关部分的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"));

问题是,对会话#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...值的,但这不是我所期望的值绑定,它会阻止用户实体被定位

如果我将hibernatetest.entity.Userid字段的类型从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如何计算UUID '473D248D-8D91-41C9-BD73-8ACA45539D79'要绑定的值'2c6d8085f...?如何让它绑定实际的UUID值


共 (2) 个答案

  1. # 1 楼答案

    Java UUIDjava.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字段是一个临时字段,而不是同时存储ID和UUID

    SQL server可能有某种特殊的UUID类,您可以在Java中使用它来转换Java UUID。也有可能是Hibernate的新版本支持映射java。util。UUID到SQL Server的UUID,但我认为这两种可能性都不是真的

    编辑:在进一步研究这个问题之后,我可以看到你的一些困惑。NHibernate似乎确实从System.GUID转换成了SQL Server的uniqueidentifier(这是有道理的,因为两者都是微软发布的)。然而,我不相信有冬眠的等价物

  2. # 2 楼答案

    我也遇到了同样的问题,我通过向列中添加uuid-char类型来解决它

    <!  User.hbm.xml  >
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http //www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    <hibernate-mapping>
        <class name="hibernatetest.entity.User" table="aspnet_Users">
            <id name="Id" type="uuid-char">
                <column name="UserId" sql-type="uniqueidentifier" not-null="true" />
            </id>
    <!  ...  >