Hibernate ManyToOne和列表

时间:2017-10-07 03:23:07

标签: java postgresql hibernate

我在父表和子表之间存在关系,其中父表具有单个主键,子表具有复合主键。但是,子表中只有一列被引用到父表中。

enter image description here

我的hibernate类是这样连接的:

父表

@Entity
@Table(name = "snippet")
public class SnippetEntity implements Serializable{

    private static final long serialVersionUID = -3220451853395334879L;

    @Id
    @Column(name = "snpt_id", nullable=false, updatable=false)
    @JsonBackReference
    private String snippetId;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "cretn_ts")
    private Date creationTimeStamp;

    @Column(name = "cretn_user_id")
    private String creationUserId;

    public String getSnippetId() {
        return snippetId;
    }
    public void setSnippetId(String snippetId) {
        this.snippetId = snippetId;
    }

    public Date getCreationTimeStamp() {
        return creationTimeStamp;
    }
    public void setCreationTimeStamp(Date creationTimeStamp) {
        this.creationTimeStamp = creationTimeStamp;
    }

    public String getCreationUserId() {
        return creationUserId;
    }
    public void setCreationUserId(String creationUserId) {
        this.creationUserId = creationUserId;
    }

    @Override
    public String toString() {
        return "SnippetEntity{" +
                "snippetId='" + snippetId + '\'' +
                '}';
    }
}

子表

@Entity
@Table(name = "snippet_detail")
public class SnippetDetailEntity implements Serializable {

    private static final long serialVersionUID = -7470223455753164243L;

    @Id
    @Column(name = "lang_cd", nullable=false, updatable=false)
    private String language;

    @Column(name = "snpt_type_cd")
    private String snippetType;

    @Column(name = "snpt_desc")
    private String snippetDescription;

    @Column(name = "snpt_txt")
    private String snippetText;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "cretn_ts")
    private Date creationTimeStamp;

    @Column(name = "cretn_user_id")
    private String creationUserId;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "updt_ts")
    private Date updatedTimeStamp;

    @Column(name = "updt_user_id")
    private String updatedUserId;

    @ManyToOne
    @JoinColumn(name="snpt_id")
    @JsonManagedReference
    private SnippetEntity snippetEntity;

    public SnippetDetailEntity() {}


    public String getLanguage() {
        return language;
    }

    public void setLanguage(String language) {
        this.language = language;
    }

    public String getSnippetType() {
        return snippetType;
    }
    public void setSnippetType(String snippetType) {
        this.snippetType = snippetType;
    }

    public String getSnippetDescription() {
        return snippetDescription;
    }
    public void setSnippetDescription(String snippetDescription) {
        this.snippetDescription = snippetDescription;
    }

    public String getSnippetText() {
        return snippetText;
    }
    public void setSnippetText(String snippetText) {
        this.snippetText = snippetText;
    }

    public Date getCreationTimeStamp() {
        return creationTimeStamp;
    }
    public void setCreationTimeStamp(Date creationTimeStamp) {
        this.creationTimeStamp = creationTimeStamp;
    }

    public String getCreationUserId() {
        return creationUserId;
    }
    public void setCreationUserId(String creationUserId) {
        this.creationUserId = creationUserId;
    }

    public Date getUpdatedTimeStamp() {
        return updatedTimeStamp;
    }
    public void setUpdatedTimeStamp(Date updatedTimeStamp) {
        this.updatedTimeStamp = updatedTimeStamp;
    }

    public String getUpdatedUserId() {
        return updatedUserId;
    }
    public void setUpdatedUserId(String updatedUserId) {
        this.updatedUserId = updatedUserId;
    }

    public SnippetEntity getSnippetEntity() { return snippetEntity; }
    public void setSnippetEntity(SnippetEntity snippetEntity) { this.snippetEntity = snippetEntity; }

    @Override
    public String toString() {
        return "SnippetDetailEntity{" +
                "language='" + language + '\'' +
                ", snippetType='" + snippetType + '\'' +
                ", snippetDescription='" + snippetDescription + '\'' +
                ", snippetText='" + snippetText + '\'' +
                ", creationTimeStamp=" + creationTimeStamp +
                ", creationUserId='" + creationUserId + '\'' +
                ", updatedTimeStamp=" + updatedTimeStamp +
                ", updatedUserId='" + updatedUserId + '\'' +
                ", snippetEntity=" + snippetEntity +
                '}';
    }
}

获取所有snippet_detail的电话是:

List<SnippetDetailEntity> snippetEntities = dbService.getAll(SnippetDetailEntity.class);

public <T> List<T> getAll(Class<T> clazz) {
    return getSession().createCriteria(clazz).list();
}

snippet_detail中有378条记录。所以,我的问题是,当我执行一个列表来获取snippet_detail的所有行时,我从snippet_detail得到两个唯一的记录(前两个与此表中的主键匹配)并且这些记录是重复的多次。记录总数仍为378,但这378条记录是由多次重复的两个记录组成的。我完全困惑的是,我承认这可能是因为我对hibernate的理解是为什么会发生这种情况?我已阅读了很多帖子,他们都在讨论hibernate做outer join。我在做什么不对劲?如果是这样,我该怎么做才能解决这个问题?

更新:

通过阅读更多博客和帖子,我意识到我的snippet_detail中有一个复合键,以及通过hibernate处理它以使用@Embeddable注释的方法。我创建了一个@Embeddable类,其中包含snpt_idlang_cd。我修改了snippet_detail实体类以使用@Embeddable类。我还将@ManyToOne联接移动到@Embeddable类,因为我认为这是我需要指定连接条件的位置(即snpt_idsnippet_detail之间的snpt_id {1}}表的{1}}。

现在,fetch运行正常,但是当我插入snippet时,我得到一个休眠错误,说它无法执行插入,因为我违反了引用键约束。在我原始帖子中的类中,snippet_detail位于子类中,在这种情况下,如果记录尚不存在,子表的插入将在父代码表中插入记录在摘录表中。

我的父表类与上面的相同。新的@ManyToOne类和我的子类被修改为:

@Embeddable

1 个答案:

答案 0 :(得分:0)

因此,对于父表具有单个主键的父子关系,child具有复合键,并且当其中一个子键具有返回父表的引用约束时,这对于我。

<强>父

@Entity
@Table(name = "snippet")
public class SnippetEntity implements Serializable{

    private static final long serialVersionUID = -3220451853395334879L;

    @Id
    @Column(name = "snpt_id", nullable=false, updatable=false)
    private String snippetId;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "cretn_ts")
    private Date creationTimeStamp;

    @Column(name = "cretn_user_id")
    private String creationUserId;
}

儿童的复合键为Embeddable:

@Embeddable
public class SnippetDetailPrimaryEntity implements Serializable{

    @Column(name = "snpt_id")
    private String snippetId;

    @Column(name = "lang_cd")
    private String language;
}

儿童

@Entity
@Table(name = "snippet_detail")
public class SnippetDetailEntity implements Serializable {

    private static final long serialVersionUID = -7470223455753164243L;

    @EmbeddedId
    private SnippetDetailPrimaryEntity snippetDetailPrimaryEntity;

    @Column(name = "snpt_type_cd")
    private String snippetType;

    @Column(name = "snpt_desc")
    private String snippetDescription;

    @Column(name = "snpt_txt")
    private String snippetText;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "cretn_ts")
    private Date creationTimeStamp;

    @Column(name = "cretn_user_id")
    private String creationUserId;

    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "updt_ts")
    private Date updatedTimeStamp;

    @Column(name = "updt_user_id")
    private String updatedUserId;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name="snpt_id", insertable = false, updatable = false)
    private SnippetEntity snippetEntity;
}