1

I have really got stuck with using Hibernate in my project. Some issues I have described here: Hibernate: getting too many rows I have started wondering if my code is correct. I am working on a huge project and I have had to define mapping classes with annotations on my own. But when the problems have began to occur I have decided to recreate part of database separate to the project and try to generate entities in IDE.

I have two tables: My and Option. My has primary key: column qwerty and property. Propertyis the foreign key from Option table. And of course Option has property as a primary key.

In my solution I have created @Embeddable MyPK class with two properties: String qwerty and String property. In my My entity I have of course @EmbeddedId MyPK and also property (the same column name as in the MyPK) but is this Option object, not String as in the MyPK.

@ManyToOne
@JoinColumn(name = "property", nullable = false, insertable = false, updatable = false)
protected Option option;

This is entity generated by Hibernate Tools in Intellij Idea. There isn't EmbeddedId, but there is @IdClass. I have thought that @IdClass is only for basic types. But I have a object as a part of my primary key. However there is also OptionEntity object here. Is this correct to keep basic type and object type for one column?

@javax.persistence.IdClass(test.go.MyEntityPK.class)
@javax.persistence.Table(name = "MY", schema = "PUBLIC", catalog = "PUBLIC")
@Entity
public class MyEntity {
    private String qwerty;

    @javax.persistence.Column(name = "QWERTY")
    @Id
    public String getQwerty() {
        return qwerty;
    }

    public void setQwerty(String qwerty) {
        this.qwerty = qwerty;
    }

    private String text;

    @javax.persistence.Column(name = "TEXT")
    @Basic
    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

    private String lang;

    @javax.persistence.Column(name = "PROPERTY")
    @Id
    public String getProperty() {
        return property;
    }

    public void setProperty(String property) {
        this.property= property;
    }

    @Override
    public boolean equals(Object o) {
        //equals
    }

    @Override
    public int hashCode() {
        //hashCode
    }

    private OptionEntity optionByProperty;

    @ManyToOne
    @javax.persistence.JoinColumn(name = "PROPERTY", referencedColumnName = "PROPERTY", nullable = false)
    public OptionEntity getOptionByProperty() {
        return optionByProperty;
    }

    public void setOptionByProperty(OptionEntity optionByProperty) {
        this.optionByProperty = optionByProperty;
    }
}

This is MyEntityPK generated class:

public class MyEntityPK implements Serializable {
    private String qwerty;

    @Id
    @Column(name = "qwerty")
    public String getQwerty() {
        return qwerty;
    }

    public void setQwerty(String qwerty) {
        this.qwerty = qwerty;
    }

    private String property;

    @Id
    @Column(name = "PROPERTY")
    public String getProperty() {
        return property;
    }

    public void setProperty(String property) {
        this.property = property;
    }

    @Override
    public boolean equals(Object o) {
        //equals
    }

    @Override
    public int hashCode() {
        //hashCode
    }
}

OptionEntity below. No special points aren't in this entity. I would like only @Version annotation on version property and also List<MyEntity> instead of Collection<MyEntity>.

@javax.persistence.Table(name = "OPTION", schema = "PUBLIC", catalog = "PUBLIC")
@Entity
public class OptionEntity {
    private Long version;

    @javax.persistence.Column(name = "VERSION")
    @Basic
    public Long getVersion() {
        return version;
    }

    public void setVersion(Long version) {
        this.version = version;
    }

    private String property;

    @javax.persistence.Column(name = "PROPERTY")
    @Id
    public String getProperty() {
        return property;
    }

    public void setProperty(String property) {
        this.property = property;
    }

    @Override
    public boolean equals(Object o) {
        //equals
    }

    @Override
    public int hashCode() {
        //hashcode
    }

    private Collection<MyEntity> myByProperty;

    @OneToMany(mappedBy = "optionByProperty")
    public Collection<MyEntity> getMyByProperty() {
        return myByProperty;
    }

    public void setMyByProperty(Collection<MyEntity> myByProperty) {
        this.myByProperty = myByProperty;
    }
}

What option is the most proper and less problematic? The one that I have described or the one that pasted?

4

2 回答 2

1

查看使用派生 ID 的 JPA 2.0 示例: http ://wiki.eclipse.org/EclipseLink/Examples/JPA/2.0/DerivedIdentifiers 这似乎是您所追求的。

在 JPA 中,您的 id 不需要 embeddedId,但如果使用复合 PK,您确实需要一个类来保存组成 pk 的多个值。此类的实例被传递给 em.find 方法,它可以是 EmbeddedId 或 PKClass。我更喜欢自己使用 PKClass,但这取决于您 - 使用嵌入式只是将字段放置在可嵌入类中,因此您可以使用嵌入式对象来设置映射并访问值。如果使用 pkClass,则不需要在其中注释的字段/属性,因为它们可以直接在实体中访问和映射。

于 2012-10-12T14:03:59.570 回答
1

摆脱财产private String lang;/private String property;它已经由多面体定义。您也不需要 MyEntity 的主键的类。MyEntity 可以是它自己的具有两个属性的 id 类,也可以是它的qwertykey option-property,key-manytoone。

于 2012-10-12T12:19:10.330 回答