Java 消除JPA中对所有者的冗余引用
我在JPA+Hibernate、Java 消除JPA中对所有者的冗余引用,java,hibernate,jpa,entity-relationship,Java,Hibernate,Jpa,Entity Relationship,我在JPA+Hibernate、Player和AvatarAttributeOwnership中拥有这些实体。前者有后者的集,定义了它拥有的化身属性 @Entity public class Player implements Serializable { @Id @GeneratedValue private long id; @OneToMany(fetch=FetchType.LAZY,mappedBy="owner",cascade=Cascade
Player
和AvatarAttributeOwnership
中拥有这些实体。前者有后者的集,定义了它拥有的化身属性
@Entity
public class Player implements Serializable {
@Id
@GeneratedValue
private long id;
@OneToMany(fetch=FetchType.LAZY,mappedBy="owner",cascade=CascadeType.ALL)
private Set<AvatarAttributeOwnership> ownedAvatarAttributes;
...
}
@Entity
@Table(uniqueConstraints=@UniqueConstraint(columnNames={"owner","gender","type","attrId"}))
public class AvatarAttributeOwnership implements Serializable {
@Id
@GeneratedValue
@SuppressWarnings("unused")
private long id;
@ManyToOne
@JoinColumn(name="owner")
private Player owner;
// these three columns define the attribute (i.e. are attribute's key)
@Column
private String attrId;
@Column
private String gender;
@Column
private String type;
@Column
private Date ownedSince;
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + attrId.hashCode();
result = prime * result + gender.hashCode();
result = prime * result + owner.hashCode();
result = prime * result + type.hashCode();
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
AvatarAttributeOwnership other = (AvatarAttributeOwnership) obj;
if (!attrId.equals(other.attrId)) return false;
if (gender != other.gender) return false;
if (!owner.equals(other.owner)) return false;
if (!type.equals(other.type)) return false;
return true;
}
}
我是否可以在保留此处定义的唯一约束的同时,删除AvatarAttributeOwnership
中的所有者引用?您可以通过定义单向多对一关联。这将生成一个连接表,其中一列为所有者id(在您的情况下为玩家),另一列为子级id(AvatarAttributeOwnership)。请参阅以获取解释(请注意映射中的unique=true)您可以通过定义单向多对一关联。这将生成一个连接表,其中一列为所有者id(在您的情况下为玩家),另一列为子级id(AvatarAttributeOwnership)。请参阅以获取解释(请注意映射中的unique=true)为了定义列“顺序”
”的唯一约束,该列显然必须出现在相应的表中。因此,您无法摆脱引用并保留约束。
您可以做的是只将Player
的主键存储在AvatarAttributeOwnership
中,但为什么要这样做呢?如果您想知道为创建AvatarAttributeOwnership实例而加载播放器实例的开销:您可以始终传递em.getReference(Player.class,playerId)
而不是真正的玩家实例,除非您访问AvatarAttributeOwnership构造函数中的任何玩家状态,否则它不会触发数据库选择。为了在列“order
”上定义唯一约束,该列显然必须出现在相应的表中。因此,您无法摆脱引用并保留约束。
您可以做的是只将Player
的主键存储在AvatarAttributeOwnership
中,但为什么要这样做呢?如果您想知道为创建AvatarAttributeOwnership实例而加载播放器实例的开销:您可以始终传递em.getReference(Player.class,playerId)
而不是真正的玩家实例,它不会触发数据库选择,除非你访问AvatarAttributeOwnership构造函数中的任何玩家状态。结果证明我真正想要的是使AvatarAttributeOwnership
@Embeddeble
结果证明我真正想要的是使AvatarAttributeOwnership
@embeddeble
我可能把示例代码缩写得太多了。巴特:注意,我提到的关联类型与你的不同:它是多对多的,unique=true。我自己按照我提供的链接中的描述使用了它,并且我不必在children中保留owner属性。我只需要在owner中定义关系:owner o1=new owner();o1.children.add(newchild());Child没有任何所有者引用,它按预期工作。我可能对示例代码进行了太多的缩写。巴特:注意,我提到的关联类型与你的不同:它是多对多的,unique=true。我自己按照我提供的链接中的描述使用了它,并且我不必在children中保留owner属性。我只需要在owner中定义关系:owner o1=new owner();o1.children.add(newchild());子项没有任何所有者引用,它按预期工作。唯一的约束是防止玩家两次拥有同一属性。然而,困难在于每个属性都由3个值定义,而不是一个值。但是,您怎么能期望能够在没有以任何方式映射的列上定义约束呢?毕竟JPA是关于O/R映射的……事实证明我真正想要的是使AvatarAttributeOwnership
可嵌入,并在Player
中收集它。生成一个带有列Player\u id
的表,而不在类中。唯一性由Set
和equals
处理,而不是由数据库处理,这是正常的,但并不理想。请参阅以获取新代码。唯一约束用于防止玩家两次拥有同一属性。然而,困难在于每个属性都由3个值定义,而不是一个值。但是,您怎么能期望能够在没有以任何方式映射的列上定义约束呢?毕竟JPA是关于O/R映射的……事实证明我真正想要的是使AvatarAttributeOwnership
可嵌入,并在Player
中收集它。生成一个带有列Player\u id
的表,而不在类中。唯一性由Set
和equals
处理,而不是由数据库处理,这是正常的,但并不理想。有关新代码,请参阅。
player = em.find(Player.class, playerId);
player.getAvatarAttributeOwnership().add(new AvatarAttributeOwnership(player, attrId, gender, type, new Date()));
em.persist(player);