Hibernate 从第三方库映射值对象

Hibernate 从第三方库映射值对象,hibernate,jpa,Hibernate,Jpa,我需要通过Hibernate注释将以下实体持久化到关系数据库: @Entity @Table(name="fizzes") public class Fizz { @Id @GeneratedValue @Column(name="fizz_id") private int id; @Column(name="fizz_wooz") private String wooz; // ??? here I am unsure! privat

我需要通过Hibernate注释将以下实体持久化到关系数据库:

@Entity
@Table(name="fizzes")
public class Fizz {
    @Id @GeneratedValue
    @Column(name="fizz_id")
    private int id;

    @Column(name="fizz_wooz")
    private String wooz;

    // ??? here I am unsure!
    private Buzz buzz;

    // Constructor, getters/setters down here, etc...
}

public class Buzz {
    private int jupiter;

    private String neptune;

    // Constructor, getters/setters down here, etc...
}
Buzz
的问题是:

  • 我不希望它成为自己的实体/表。我希望它是一个映射到
    fizzes
    表的“值对象/类型”(通过向其添加列)
  • Buzz
    来自第三方库,因此我无法修改它
因此,我要寻找的最终结果(以表格形式)是:

[fizzes] table
==============
fizz_id, PRIMARY KEY AUTO INCREMENT
fizz_wooz, NVARCHAR(50) NOT NULL
fizz_buzz_jupiter, INT NOT NULL
fizz_buzz_neptune, NVARCHAR(100) NOT NULL

当我无法修改
Buzz
时,如何让Hibernate进行这种基于注释的映射?

我想您希望
Buzz
对象的属性出现在
Fizz
对象中,这意味着
Buzz
Fizz
的属性都应该作为列出现在同一个表中
fizzes

因此,您必须扩展
Fizz
对象,其中
Buzz
将被注释为
@MappedSuperClass

@Entity
@Table(name="fizzes")
public class Fizz extends Buzz {
    // Fizz properties
    // No need to add Buzz as a field
}

@MappedSuperclass
public class Buzz {
    // Buzz properties
}

如果不添加
@MappedSuperclass
注释,则无法实现此目的。即使
Buzz
Fizz
扩展,Hibernate也不会识别
Buzz
的字段,因为Hibernate只反映
Fizz
中的字段,而不会反映在extended
Buzz
类中的字段上,除非您指定
@MappedSuperclass
注释。MappedSuperclass将告诉hibernate在
Buzz
对象的字段上也使用反射

您正在搜索的是可嵌入的

@Entity
public class Fizz {
    ...

    @Embedded
    private Buzz buzz;

}
您可以仅为
Buzz
定义映射文件:

<entity-mappings version="1.0" xmlns="http://java.sun.com/xml/ns/persistence/orm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm    
                        http://java.sun.com/xml/ns/persistence/orm_1_0.xsd">
    <embeddable class="...Buzz">
        <attributes>
            <basic name="jupiter"><column name="fizz_buzz_jupiter"/></basic>
            <basic name="neptune"><column name="fizz_buzz_neptune"/></basic>
        </attributes>
    </embeddable>
</entity-mappings>
如果您确实想为
Buzz
使用注释:您不能为其他类定义注释。这就是注释的含义:它们是内联的,属于它们的类。否则,与映射文件相比将没有任何好处

但您可以扩展Buzz,并将其与属性访问一起使用:


唯一的缺点:您不能在
Fizz
中使用
Buzz
的实例,谢谢@user1354678(+1)-但是,我不能修改
Buzz
源代码!!!换句话说,我不能添加
@MappedSuperclass
…想法?@DirtyMikeAndTheBoys,我已经更新了我的答案。没有
@MappedSuperclass
注释,我没有尝试过。我想hibernate的工作方式就是我在上一篇文章中解释的。也许您尝试不使用
@MappedSuperclass
注释。再次感谢@user1354678,但您真的是说Hibernate不能或/M由第三方创建/拥有的类吗?例如,如果Maven Central的某个第三方JAR包含一些我希望作为值对象/类型持久化的类,您告诉我,如果不修改它们的源代码以包含
@MappedSuperclass
?!?,就无法做到这一点?!?!如果那是真的,那我就完完全全被雷了@DirtyMikeAndTheBoys,我说可以通过在父类中将第三方的字段定义为字段来将其用作子表,但如果通过在父类中扩展它来使用第三方类,则不能。正如我前面所说,我没有尝试过没有
@MappedSuperclass
注释的情况,也许您可以尝试,但我假设结果不会反映该字段。看起来有了
@Embedded
annotation@user1354678:您错过了可嵌入的
概念。使用
MappedSuperclass
将属性放在同一个表中会导致糟糕的类设计。非常感谢@Tobias Liefke(+1和绿色复选框)@是的,我没有源代码,也不想因为修改类而违反任何许可。至于为什么我需要注释而不是映射文件,我只是更喜欢注释,因为它们更干净(IMHO)。再次感谢你的帮助!
<persistence-unit>
    <mapping-file>.../orm.xml</mapping-file>
</persistence-unit>
@Entity
public class Fizz {
    ...

    @Embedded
    private BuzzExtension buzz;

}

@Embeddable
@Access(AccessType.PROPERTY)
public class BuzzExtension extends Buzz {
    @Column(name="fizz_buzz_jupiter")
    public int getJupiter() {
        return super.getJupiter();
    }

    @Column(name="fizz_buzz_neptune")
    public String getNeptune() {
        return super.getNeptune();
    }

}