获取具有 uniqueidentifier 主键的实体时出现问题

发布于 2024-10-14 05:31:28 字数 2869 浏览 5 评论 0原文

为了调查 Hibernate 的行为是否与 NHibernate 的针对特定使用场景不同,我开始编写一个 Java SE &我的基于 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"));

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

如果我将 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

How did Hibernatecalculate the value '2c6d8085f... to Bind for the UUID '473D248D-8D91-41C9- BD73-8ACA45539D79'?如何让它绑定实际的 UUID 值?

In order to investigate whether Hibernate's behavior is different than NHibernate's for a particular usage scenario, I began writing a Java SE & Hibernate port of the relevant parts of my NHibernate-based application, but encountered a problem with obtaining an entity where the corresponding SQL Server 2008 R2 Express table uses a uniqueidentifier for the primary key.

Here's the mapping file:

<!-- 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>
    <!-- ... -->

And corresponding POJO definition:

// 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;
    }
    //...

And main code:

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"));

The problem is that the call to Session#get returns null, as it fails to find the user entity for primary key '473D248D-8D91-41C9-BD73-8ACA45539D79'.

When I enable full logging, I see:

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

I don't know how Hibernate derived the value '2c6d8085f..., but this is not the value binding that I expected, and it prevents the user entity from being located.

If I change the type of the id field of hibernatetest.entity.User from java.util.UUID to String, then this line succeeds in finding the entity:

User currentUser = (User) session.get(User.class, "473D248D-8D91-41C9-BD73-8ACA45539D79");

And the log output becomes:

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

How did Hibernate calculate the value '2c6d8085f... to bind for the UUID '473D248D-8D91-41C9-BD73-8ACA45539D79'? How can I make it bind the actual UUID value instead?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

天生の放荡 2024-10-21 05:31:28

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 字段是一个瞬态字段,并且不会尝试同时存储 ID 和 UUID。

SQL Server 可能有某种特殊的 UUID 类,您可以在 Java 中使用它来与 Java UUID 相互转换。也有可能 Hibernate 的某些新版本已经支持将 java.util.UUID 映射到 SQL Server 的 UUID,但我认为这两种可能性都不成立。

编辑:进一步研究问题后,我可以看到您的一些困惑。看来NHibernate 实际上确实从System.GUID 转换为SQL Server 的uniqueidentifier(这是有道理的,因为两者都与Microsoft 相关)。然而,我不相信有 Hibernate 的等价物。

The Java UUID (java.util.UUID) and the SQL Server uniqueidentifier are two different things. You are telling Hibernate to map between the two. I'm surprised Hibernate is able to do anything at all, and not surprised that what it does generate is very strange.

As best I know (don't do much work with SQL Server) Hibernate is going to treat the uniqueidentifier as a plain old String column. As such, your best bet would probably be to map it a String. You could still have a getUUID() and setUUID() as...

public UUID getUUID() {
    return UUID.fromString(id);
}

public void setUUID(UUID val) {
    id = val.toString();
}

Just make sure if you're doing property-based mapping that Hibernate knows the UUID field is a transient field and doesn't try to store both the ID and the UUID.

It's possible that SQL server has some kind of special UUID class you could use in Java that can convert to/from the Java UUID. It's also possible that some new version of Hibernate has come out with support for mapping java.util.UUID to SQL Server's UUID but I don't think either of these possibilities are true.

Edit: After looking into the problem further I can see some of your confusion. It appears that NHibernate DOES in fact convert from System.GUID to SQL Server's uniqueidentifier (makes sense since both are Microsoft-releated). However, I don't believe there is a Hibernate equivalent.

橙幽之幻 2024-10-21 05:31:28

我遇到了同样的问题,我通过向列添加 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>
<!-- ... -->

I had the same problem and I solved it by adding uuid-char type to column.

<!-- 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>
<!-- ... -->
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文