获取具有uniqueidentifier主键的实体时出现问题 [英] Problem obtaining entities with uniqueidentifier primary key

查看:154
本文介绍了获取具有uniqueidentifier主键的实体时出现问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了调查Hibernate的行为与NHibernate的对于特定的使用场景是否不同,我开始编写Java SE &安培;我的基于NHibernate的应用程序的相关部分的Hibernate端口,但遇到与获取实体相关的SQL Server 2008 R2 Express表使用 uniqueidentifier 作为主键的问题。



以下是映射文件:

 <! - User.hbm.xml  - > 
<?xml version =1.0encoding =UTF-8?>
<!DOCTYPE hibernate-mapping PUBLIC - // Hibernate / Hibernate Mapping DTD 3.0 // ENhttp://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd\">
< hibernate-mapping>
< class name =hibernatetest.entity.Usertable =aspnet_Users>
< id name =Id>
< column name =UserIdsql-type =uniqueidentifiernot-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 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) - 从aspnet_Users user0_中选择user0_.UserId作为UserId0_0_,其中user0_.UserId =? 
Hibernate:从aspnet_Users user0_中选择user0_.UserId作为UserId0_0_,其中user0_.UserId =?
TRACE [主要](NullableType.java:133) - 结合 '2c6d8085f3f2808eeae1f6e1aef5f4e9ecaed5d5c9c43c19837718ed05af828082ca808cece5e1f3f4d3e9e7c2e9f4f3ca808bedeff3f4d3e9e7c2e9f4f3f8f03df30a4ac5d31df9c7bda40d0d11c149' 到参数:1个

我不知道Hibernate如何派生出值'2c6d8085f ... ,但这不是我期望的值绑定,并且它阻止了用户实体

如果我更改 hibernatetest.entity的 id 字段的类型.User 从 java.util.UUID 字符串,那么这行代表成功地找到实体:

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

然后日志输出变成:

  DEBUG [main](AbstractBatcher.java:401) - 从aspnet_Users user0_中选择user0_.UserId作为UserId0_0_,其中user0_.UserId =? 
Hibernate:从aspnet_Users user0_中选择user0_.UserId作为UserId0_0_,其中user0_.UserId =?
TRACE [main](NullableType.java:133) - 绑定'473D248D-8D91-41C9-BD73-8ACA45539D79'至参数:1

Hibernate如何计算值'2c6d8085f ... 以绑定UUID '473D248D-8D91 -41C9-BD73-8ACA45539D79' ?我怎样才能让它绑定实际的UUID值呢?

UUID java.util.UUID )和SQL Server uniqueidentifier 是两个不同的东西。您正在告诉Hibernate在两者之间进行映射。我很惊讶Hibernate能够做任何事情,并且不奇怪它产生的东西是非常奇怪的。



据我所知(不要做太多事情使用SQL Server)Hibernate将把 uniqueidentifier 视为普通的旧String列。因此,您最好的选择可能是将其映射为字符串。您仍然可以将 getUUID() setUUID()作为...

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


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

$ / code>

只要确定您是否在执行Hibernate知道的基于属性的映射UUID字段是一个临时字段,不会尝试存储ID和UUID。



有可能SQL服务器有某种您可以使用的特殊UUID类在Java中可以转换成Java UUID或从Java UUID转换。也有可能某些新版本的Hibernate已经支持将java.util.UUID映射到SQL Server的UUID,但我不认为这两种可能性都是真的。



编辑:进一步调查问题后,我可以看到你的一些混乱。看起来NHibernate DOES实际上是从 System.GUID 转换为SQL Server的 uniqueidentifier (这很合理,因为它们都是Microsoft-相关型号)。但是,我不相信有一个Hibernate的等价物。


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?

解决方案

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.

这篇关于获取具有uniqueidentifier主键的实体时出现问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆