JPA / hibernate - 无法添加或更新子行:外键约束失败。无法插入null

时间:2013-05-20 08:31:01

标签: hibernate jpa

我正在尝试实现manyToMany关系。将数据从数据库获取到实体时工作正常但在尝试将新值插入连接表时失败。 我有三张桌子:job,job_prozedur和prozedur。连接表包含父表(作业和prozedur)的外键以及少量额外列。

实体类是:

@Entity
@Table(name = "DOK_JOB")
Public class Job implements Serializable {

private static final long serialVersionUID = 1L;

private Integer id;
private String name;    

private List<JobProzedur> jobProzedurList = new ArrayList<JobProzedur>();

public Job() {}

@Id
@SequenceGenerator(name="seqJob", sequenceName="DOK_SEQ_1", allocationSize=1)
@GeneratedValue(generator="seqJob")
@Column(name = "JOB_ID")
public Integer getId() {
    return id;
}

public void setId(Integer id) {
    this.id = id;
}   

@Column(name = "JOB_NAME")
public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

@OneToMany(fetch = FetchType.EAGER, mappedBy = "job", cascade = CascadeType.ALL, orphanRemoval=true)
@OrderBy(value = "sortLnr")
@Cascade({org.hibernate.annotations.CascadeType.ALL})
public List<JobProzedur> getJobProzedurList() {
    return jobProzedurList;
}

public void setJobProzedurList(List<JobProzedur> jobProzedurList) {
    this.jobProzedurList = jobProzedurList;
}

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((id == null) ? 0 : id.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;
    Job other = (Job) obj;
    if (id == null) {
        if (other.id != null)
            return false;
    } else if (!id.equals(other.id))
        return false;
    return true;
}
}

-

@Entity
@Table(name = "DOK_JOB_PROZEDUR")
public class JobProzedur implements Serializable {

private static final long serialVersionUID = 7971463524201735449L;

private JobProzedurId id = new JobProzedurId();
private Integer sortLnr;

private Job job;
private Prozedur proz;

public JobProzedur() {}

@EmbeddedId
public JobProzedurId getId() {
    return id;
}

public void setId(JobProzedurId id) {
    this.id = id;
}

@Column(name = "SORT_LNR")
public Integer getSortLnr() {
    return sortLnr;
}

public void setSortLnr(Integer sortLnr) {
    this.sortLnr = sortLnr;
}   

@ManyToOne(fetch=FetchType.EAGER)
@JoinColumn(name = "JOB_ID", referencedColumnName = "JOB_ID", insertable=false, updatable=false, nullable=false)
public Job getJob() {
    return job;
}

public void setJob(Job job) {
    this.job = job;
}

@ManyToOne(fetch=FetchType.EAGER)
@JoinColumn(name = "PROZ_ID", referencedColumnName = "PROZ_ID", insertable=false, updatable=false)
public Prozedur getProz() {
    return proz;
}

public void setProz(Prozedur proz) {
    this.proz = proz;
}

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((id == null) ? 0 : id.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;
    JobProzedur other = (JobProzedur) obj;
    if (id == null) {
        if (other.id != null)
            return false;
    } else if (!id.equals(other.id))
        return false;
    return true;
}   

}

-

@Embeddable
public class JobProzedurId implements Serializable {

private static final long serialVersionUID = 1L;    

private Integer jobId;
private Integer prozId; 

public JobProzedurId() {}   

public JobProzedurId(Integer jobId, Integer prozId) {
    super();
    this.jobId = jobId;
    this.prozId = prozId;
}

@Column(name = "JOB_ID", nullable=false)
public Integer getJobId() {
    return jobId;
}

public void setJobId(Integer jobId) {
    this.jobId = jobId;
}

@Column(name = "PROZ_ID")
public Integer getProzId() {
    return prozId;
}

public void setProzId(Integer prozId) {
    this.prozId = prozId;
}

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((jobId == null) ? 0 : jobId.hashCode());
    result = prime * result + ((prozId == null) ? 0 : prozId.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;
    JobProzedurId other = (JobProzedurId) obj;
    if (jobId == null) {
        if (other.jobId != null)
            return false;
    } else if (!jobId.equals(other.jobId))
        return false;
    if (prozId == null) {
        if (other.prozId != null)
            return false;
    } else if (!prozId.equals(other.prozId))
        return false;
    return true;
}

@Override
public String toString() {
    return "JobProzedurId [jobId=" + jobId + ", prozId=" + prozId + "]";
}

}

-

@Entity
@Table(name = "DOK_PROZEDUR")
public class Prozedur implements Serializable {

private static final long serialVersionUID = 1L;

private Integer id;
private String dbName;
private String schemaName;
private String packageName;
private String name;

public Prozedur() {}

@Id
@SequenceGenerator(name="seqProz", sequenceName="DOK_SEQ_1", allocationSize=1)
@GeneratedValue(generator="seqProz")
@Column(name = "PROZ_ID")
public Integer getId() {
    return id;
}

public void setId(Integer id) {
    this.id = id;
}

@Column(name = "DB_NAME")
public String getDbName() {
    return dbName;
}

public void setDbName(String dbName) {
    this.dbName = dbName;
}

@Column(name = "SCHEMA_NAME")
public String getSchemaName() {
    return schemaName;
}

public void setSchemaName(String schemaName) {
    this.schemaName = schemaName;
}

@Column(name = "PACKAGE_NAME")
public String getPackageName() {
    return packageName;
}

public void setPackageName(String packageName) {
    this.packageName = packageName;
}

@Column(name = "PROZ_NAME")
public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((id == null) ? 0 : id.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;
    Prozedur other = (Prozedur) obj;
    if (id == null) {
        if (other.id != null)
            return false;
    } else if (!id.equals(other.id))
        return false;
    return true;
}

}

我将prozedur分配给作业并持久化的代码部分是:

//      ...
//      ...
    JobProzedur jobProz = new JobProzedur();
    jobProz.setJob(job);
    jobProz.setProz(proz);

    job.getJobProzedurList().add(jobProz);

    entityManager.persist(job);
    entityManager.flush();

持续存在时我会遇到异常:

org.hibernate.exception.ConstraintViolationException: ORA-01400: cannot insert NULL into ("DOK"."DOK_JOB_PROZEDUR"."JOB_ID")

我不知道为什么hibernate在persist期间没有为连接表中的外键列赋值。更新有效,因为我手动分配这些值,但这不是正确的方法。任何帮助表示赞赏。我已经在这几天工作了,我看不到任何解决方案。请帮忙!

1 个答案:

答案 0 :(得分:1)

您忘记在JobProzedur.getProz()JobProzedut.getJob()

上添加@MapsId注释

编辑:正如@PepperBob所说:关联不应该标记为insertable = false和updatable = false,因为你只想插入它们。

但是,通过使用单列自动生成的主键而不是复合主键,我可以让我的生活更轻松,应用程序更快。使用唯一约束来保证不能存在具有相同作业ID和相同prozedur ID的两行。