Problem obtaining entities with uniqueidentifier primary key

末鹿安然 提交于 2019-12-24 00:47:06

问题


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?


回答1:


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.




回答2:


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


来源:https://stackoverflow.com/questions/4787906/problem-obtaining-entities-with-uniqueidentifier-primary-key

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!