I am trying to map a bi-directional (one to many and many to one) relationship in Hibernate. We're getting errors when attempting save a result.
The error we're getting is:
Caused by: org.hibernate.PropertyValueException: not-null property references a null or transient value : com.example.Component.resultId at org.hibernate.engine.internal.Nullability.checkNullability(Nullability.java:92)
From the source code below a Result
can have many Component
s and many Component
s can belong to a single Result
. One of the requirement is that the resultId
in Result
must be a String
. This requirement is out of our control.
An example Entity source code is below:
@Entity
@Table(name = "result")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class Result extends AbstractEntity {
@OneToMany(cascade = CascadeType.MERGE)
@JoinColumn(name = "resultId")
private List<Component> component = new ArrayList<>();
}
@Entity
@Table(name = "cmpt")
@XmlRootElement
public class Component extends AbstractEntity {
@ManyToOne(targetEntity = Result.class)
private String resultId;
}
Here is the solution that worked for me
@Entity
@Table(name = "result")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class Result extends AbstractEntity {
@OneToMany(cascade = CascadeType.MERGE, nullable = false)
@JoinColumn(name = "resultId")
private List<Component> component = new ArrayList<>();
}
@Entity
@Table(name = "cmpt")
@XmlRootElement
public class Component extends AbstractEntity {
@Column(name = "result_id", insertable = false, updatable = false, nullable = false)
private String resultId;
}
The correct way to create a bidirectional entity is this.
@Entity
@Table(name = "result")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class Result extends AbstractEntity {
@OneToMany(cascade = CascadeType.MERGE, mappedBy="result")
private List<Component> component = new ArrayList<>();
}
@Entity
@Table(name = "cmpt")
@XmlRootElement
public class Component extends AbstractEntity {
@ManyToOne(targetEntity = Result.class)
@JoinColumn(name = "result_id") //result_id is the column name (foreign key) in cmpt table
private Result result;
@Column(name = "result_id", insertable = false, updatable = false)
private String resultId;
}
This will ensure there will be only one bi-direction relation (not two uni-directional relations etc). Let me know if you are expecting something else.
Update 1:
You can add another key to the entity as specified above. You'll get the foreign key as a string. But you need to remember that the actual mapping with JoinColumn should not be removed. I have tested the above configuration and it seems to work for me.
You have to declare an entity as the field annotated with @ManyToOne. Also i think in your case you should put the @Join column on the Component side:
@Entity
@Table(name = "cmpt")
@XmlRootElement
public class Component extends AbstractEntity {
@ManyToOne
@JoinColumn(name = "resultId")
private Result result;
}
now you dont need the targetEntity
attrbute.
Also remove the @JoinColumn
from @OneToMany
and add mappedBy
attribute:
@Entity
@Table(name = "result")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class Result extends AbstractEntity {
@OneToMany(cascade = CascadeType.MERGE, mappedBy="result")
private List<Component> component = new ArrayList<>();
}
我认为您必须从Component.java类中删除@ManyToOne(targetEntity = Result.class)
批注,并且当您尝试保存数据时,首先必须使用save方法保存Result ,然后通过save方法将返回的resultId设置为此使用setter和getter在组件实体中的resultId ,然后保存组件
Here is the solution that worked for me:
@Entity
@Table(name = "result")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public abstract class Result extends AbstractEntity {
@OneToMany(cascade = CascadeType.MERGE, nullable = false)
@JoinColumn(name = "resultId")
private List<Component> component = new ArrayList<>();
}
@Entity
@Table(name = "cmpt")
@XmlRootElement
public class Component extends AbstractEntity {
@Column(name = "result_id", insertable = false, updatable = false, nullable = false)
private String resultId;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.