我有一个只包含 2 个字段的表。该表具有由这两个字段组成的复合 PK。
当使用 Netbeans 从数据库创建实体 bean 时,实体 bean 不会像其他具有 2 个以上字段的表一样自动创建。
所以我想我需要自己创建实体bean。创建此实体 bean 的最佳实践是什么?它是否必须包含COMPOSITE KEY
对象?
我有一个只包含 2 个字段的表。该表具有由这两个字段组成的复合 PK。
当使用 Netbeans 从数据库创建实体 bean 时,实体 bean 不会像其他具有 2 个以上字段的表一样自动创建。
所以我想我需要自己创建实体bean。创建此实体 bean 的最佳实践是什么?它是否必须包含COMPOSITE KEY
对象?
我不使用 NetBeans,所以我不能真正谈论它的映射工具。
对于映射复合键,有几个选项。你可以
@Embeddable
使用 PK 字段定义一个单独的对象,并@EmbeddedId
在您的@Entity
类中使用它
@Embeddable
public class MyCompositePK {
@Column
private String fieldA;
@Column
private String fieldB;
}
@Entity
public class MyBean {
@EmbeddedId
private MyCompositePK id;
@Column
private String fieldC;
}
使用 PK 字段定义一个非映射 POJO,并像@IdClass
在@Entity
.
@Entity
@IdClass(value=ClassAB.ClassABId.class)
public class ClassAB implements Serializable {
private String idA;
private String idB;
@Id
@Column(name="ID_A")
public String getIdA(){ return idA; }
public void setIdA(String idA){ this.idA = idA; }
@Id
@Column(name="ID_B")
public String getIdB(){ return idB; }
public void setIdB(String idB){ this.idB = idB; }
static class ClassABId implements Serializable {
private String idA;
private String idB;
public String getIdA(){ return idA; }
public void setIdA(String idA){ this.idA = idA; }
public String getIdB(){ return idB; }
public void setIdB(String idB){ this.idB = idB; }
// implement equals(), hashcode()
}
}
在这个例子ClassABId
中是一个静态内部类只是为了方便。
Pascal Thivent 对这个问题的出色回答也解释了这些选项:如何使用 Hibernate 映射复合键?.
这个相关问题讨论了这些方法之间的差异:我应该使用哪个注释:@IdClass 或 @EmbeddedId。请注意,字段的声明与该@IdClass
方法重复。
无论如何,我认为除了创建两个类之外别无选择。这就是我问这个问题的原因:映射一个只包含没有 @IdClass 或 @EmbeddedId 的复合 PK 的类。似乎有一个特定于休眠的功能。
附带说明一下,如果您可以控制数据库结构,您还可以考虑避免使用复合键。有一些理由这样做。
谢谢@XaviLópez。您的解释修复了我的代码,该代码被声明为@Tom Anderson 提到的自己的 IdClass。当我声明它自己的具有 2 个 @Id 列的 IdClass 时,获取该实体列表的 JPA 查询在结果列表中返回预期的“n”个项目,但该列表中的每个项目都是空的。但是这个大小“n”是预期的。更改为较少重构的静态内部类后,它能够返回正确的结果集。
据我说:自我引用 IdClass 不会起作用,因为自我已经是一个实体,需要在持久性上下文中。如果我还有一个相同类型的主键对象,那么持久化上下文中就会有两个“相同”的对象。所以,它不应该被允许。因此,我们不应该使用自引用@IdClass。创建一个静态内部类作为侵入性较小的主键类型。