我试图在使用UUID作为主键的PostgreSQL中保留一个实体。我尝试将其持久保存为普通的UUID:
@Id @Column(name = "customer_id") private UUID id;
有了以上,我得到这个错误:
ERROR: column "customer_id" is of type uuid but expression is of type bytea Hint: You will need to rewrite or cast the expression. Position: 137
我也尝试将UUID保留为byte []无济于事:
@Transient private UUID id; @Id @Column(name = "customer_id") @Access(AccessType.PROPERTY) @Lob protected byte[] getRowId() { return id.toString().getBytes(); } protected void setRowId(byte[] rowId) { id = UUID.fromString(new String(rowId)); }
如果删除@Lob,我得到的错误与上面发布的错误相同。但是使用@Lob时,错误会稍微更改为:
ERROR: column "customer_id" is of type uuid but expression is of type bigint Hint: You will need to rewrite or cast the expression. Position: 137
无法完成如此简单的操作,我感到非常难过!
我正在将Hibernate 4.1.3.Final与PostgreSQL 9.1一起使用。
我在相同的问题上或多或少地看到过许多问题,但它们都是古老的,似乎没有一个简单的答案。
我想以一种标准的方式来实现这一目标,而不必借助丑陋的骇客。但是,如果只能通过(丑陋的)骇客才能做到这一点,那可能就是我要做的。但是,我不想将UUID作为varchar存储在数据库中,因为这不利于性能。另外,如果可能的话,我不想在代码中引入Hibernate依赖关系。
任何帮助将不胜感激。
更新1 (2012-07-03 12:15 pm)
好吧,好吧,好吧…我使用JTDS驱动程序(v1.2.5)和SQL Server 2008 R2测试了完全相同的代码(普通UUID,无转换- 以上发布的代码的第一版),这有点有趣。 ,猜猜是什么,它起到了作用(当然,我不得不在persistence.xml中更改与连接有关的信息)。
现在,这是特定于PostgreSQL的问题还是什么?
不幸的是,PostgreSQL JDBC驱动程序选择了一种表示非JDBC标准类型代码的方式。他们只是将它们全部映射到Types.OTHER。简而言之,您需要启用特殊的Hibernate类型映射来处理UUID映射(到特定于postgres的uuid数据类型的列):
@Id @Column(name = "customer_id") @org.hibernate.annotations.Type(type="org.hibernate.type.PostgresUUIDType") private UUID id;
或更简洁地:
@Id @Column(name = "customer_id") @org.hibernate.annotations.Type(type="pg-uuid") private UUID id;
另一个(更好)的选择是将org.hibernate.type.PostgresUUIDType注册为所有以java.util.UUID公开的属性的默认Hibernate类型映射。文档@ http://docs.jboss.org/hibernate/orm/4.1/manual/en-US/html/ch06.html#types- registry中对此进行了介绍