将JPA实体与特定于Hibernate的调整分开

时间:2011-01-30 09:40:52

标签: java hibernate jpa persistence jpa-2.0

我有以下“root”实体(特定于hibernate的部分已注释掉):

@Entity
//@GenericGenerator(name="system-uuid",strategy="org.hibernate.id.UUIDGenerator")
public class Node extends PersistentEntity {
    private UUID id;
    private String name;
    private String displayName;

    @Id
    @GeneratedValue
    //@GeneratedValue(generator="system-uuid") //instead of above line
    //@Type(type = "pg-uuid")
    public UUID getId() { return id; }

    public String getName() { return name; }

    public String getDisplayName() { return displayName; }

    //stuff omitted
}

这是使用PostgreSQL 9为数据库(使用最新的JDBC4驱动程序)部署在JBoss AS 6(hibernate 3.6)上的持久性上下文的一部分。 PostgreSQL有自己的uuid列类型,需要一些特定于hibernate的映射才能正确使用(在上面的代码中注释掉) - 否则hibernate将尝试将UUID字段映射到BINARY,然后PostgreSQL方言不支持BINARY(显然是因为postgre有两种方式存储二进制和hibernate devs不喜欢它)并且整个事情都爆炸了。

取消注释上面的行会产生工作代码,但它迫使我对hibernate有一个编译时依赖 - 我宁愿避免。

尝试将hbm.xml文件添加到混合中并从persistence.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 package="package">
    <class name="Node">
        <id name="id" type="pg-uuid">
            <generator class="org.hibernate.id.UUIDGenerator"/>
        </id>
    </class>
</hibernate-mapping>

我可以通过添加额外的2个属性来“填充”此文件,但即使我这样做(此时Node类也可以),添加任何额外的实体,例如:

@Entity
public class Host extends Node {
    //fields, getters, fluff
}

我得到以下例外:

org.hibernate.DuplicateMappingException: Duplicate class/entity mapping Node

因为hibernate“发现”Node两次。这周围有什么优雅的方式吗?理想情况下,Node是我需要特定于hibernate的属性的唯一类,它将成为大型类层次结构的根。我想避免在hibernate上编译时依赖,或者在hbm.xml中完全映射所有内容。为了完整起见,这里使用的是persistence.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
    <persistence-unit name="myPU" transaction-type="JTA">
        <jta-data-source>java:/my-postgresql-DS</jta-data-source>
        <mapping-file>META-INF/hbm.xml</mapping-file>
        <!-- shouldnt need to list classes here since this is deployed -->
        <!-- in the same jar as the classes and scanning should work   -->
        <validation-mode>AUTO</validation-mode>
        <properties>
            <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
        </properties>
    </persistence-unit>
</persistence>

3 个答案:

答案 0 :(得分:1)

我有一些建议可能会简化或解决问题,但我没有回答有关hbm.xml的具体问题。

1)您可以手动生成ID。不要使用@GeneratedValue,我相信您可以使用Java的UUID.randomUUID()生成符合RFC 4122的UUID,如Hibernate的'uuid2'生成器。我没有在Hibernate中使用那个特定的生成器,但如果你想要的只是一个有效的UUID,看起来手动生成它可能会帮助你避免一些配置舞蹈。

2)我个人只是在varchar列中的PostgreSQL中存储UUID(尽管是非id列)。我发现在数据库调查的时候,我正在从日志文件中剪切和粘贴UUID,这使得查询更容易。当UUID存储为BINARY时,这是不可能的,这就是我们将它们更改为varchar的原因。我们考虑了UUID列,但varchar使得这么多东西变得更简单并且提高了互操作性。在Java类中封装String-to-UUID转换是微不足道的。

当然,出于遗留原因,您可能必须使用UUID列类型,或者出于性能原因,您可能更喜欢使用UUID列类型。至少有一个人做过performance comparison of the two approaches

答案 1 :(得分:0)

您可以尝试将@ Entity-annotation从Node-class中删除,并将其完全映射到hbm.xml中,或者在persistence.xml中列出除Node之外的所有类,并使用&lt; exclude-unlisted-classes /&gt ;,然后将其映射到hbm.xml中。不知道这些方法中的任何一个是否真的有效,后者实际上也可能阻止hbm.xml映射类。

答案 2 :(得分:0)

答案是无法完成(至少在JPA 2.0中)