Is this correct (better) object relational mapping?

亡梦爱人 提交于 2020-01-14 04:07:26

问题


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?


回答1:


get rid of property private String lang;/private String property; it is already defined by the manytoone. you also don't need a class for the primary key of MyEntity. MyEntity can be its own id class with the two properties qwerty and option as its key-property, key-manytoone.




回答2:


Check out JPA 2.0 examples using derived Ids: http://wiki.eclipse.org/EclipseLink/Examples/JPA/2.0/DerivedIdentifiers which seem to be what you are after.

In JPA, you do not need an embeddedId for your ids, but if using a composite PK, you do need a class to hold the multiple values that make up the pk. Instances of this class are passed to the em.find method, and it can be either an EmbeddedId or a PKClass. I prefer using PKClass myself, but its up to you - using an embedded just places the fields within the embeddedable class, so you use the embedded object to set the mappings and access the values. If using a pkClass, you do not need the fields/properties annotated within it since they are accessed and mapped within the entity directly.



来源:https://stackoverflow.com/questions/12849545/is-this-correct-better-object-relational-mapping

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!