摆脱JPA中对所有者的冗余引用

时间:2011-07-08 14:28:51

标签: java hibernate jpa entity-relationship

我在JPA + Hibernate中有这些实体,PlayerAvatarAttributeOwnership。前者有Set后者,它定义了它拥有的化身属性。

@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;
    }

}

AvatarAttributeOwnerships的创建方式如下:

                player = em.find(Player.class, playerId);
                player.getAvatarAttributeOwnership().add(new AvatarAttributeOwnership(player, attrId, gender, type, new Date())); 
                em.persist(player);

我可以删除AvatarAttributeOwnership中的所有者引用,同时保持在那里定义的唯一约束吗?

3 个答案:

答案 0 :(得分:0)

您可以通过定义单向多对一关联来实现。这将生成一个连接表,其中包含所有者的id(在您的情况下是Player)的列和另一个具有子ID(AvatarAttributeOwnership)的列。有关说明,请参阅http://docs.jboss.org/hibernate/core/3.3/reference/en/html/associations.html#assoc-unidirectional-join-12m(注意映射中的unique = true)

答案 1 :(得分:0)

为了在列“order”上定义唯一约束,此列显然存在于相应的表中。所以你无法摆脱引用保持约束 您可以做的只是在Player中仅存储AvatarAttributeOwnership的主键,但为什么要这样做?如果您想知道为创建AvatarAttributeOwnership实例而加载Player实例的任何开销:您可以始终传递em.getReference(Player.class, playerId)而不是不触发数据库选择的真实播放器实例,除非您访问任何播放器状态AvatarAttributeOwnership的构造函数。

答案 2 :(得分:0)

原来我想要的是AvatarAttributeOwnership @Embeddable