问题描述
我正在使用Spring Data JPA和Spring Data Rest。 发出REST请求以保留实体时,出现下一个错误:
org.springframework.dao.DataIntegrityViolationException: not-null property references a null or transient value
我的数据模型具有以下实体:
合同:
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(discriminatorType = DiscriminatorType.STRING)
public class Contract implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(
cascade = CascadeType.ALL,orphanRemoval = true,fetch = FetchType.LAZY,mappedBy="contract"
)
private List<Participation> participants = new ArrayList<Participation>();
private String name;
}
参与:
@Entity
public class Participation implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(nullable = false) //By default the column will be CONTRACT_ID
private Contract contract;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(nullable = false)
private Contact contact;
private String clauses;
}
联系方式:
@Entity
public class Contact implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String emailAddress;
}
我有2个JPAR存储库:
public interface ContractRepository extends JpaRepository<Contract,Long> {
List<Contract> findByNameContainsIgnoreCase(String name);
}
public interface ContactRepository extends JpaRepository<Contact,Long> {
}
要保存有几个参与者的新合同,我在邮递员中进行下一步:
- 创建合同并获取其href:
请求:POST http:// localhost:8080 / api / contracts
身体:
{
"name": "Contract1"
}
响应成功:
201 Created
{
"name": "Contract1","participants": [],"_links": {
"self": {
"href": "http://localhost:8080/api/contracts/4"
},"contract": {
"href": "http://localhost:8080/api/contracts/4"
},}
}
- 到目前为止一切顺利。既然合同已经生效,我将添加参与者: 联系人1已存在于数据库中。
请求:PATCH http:// localhost:8080 / api / contracts / 4
身体:
{
"participants": [
{
"clauses": "Bla bla bla","contact": {
"href": "http://localhost:8080/api/contacts/1"
},"contract": {
"href": "http://localhost:8080/api/contracts/4"
}
}
]
}
执行此请求时,系统会抱怨现场/ fk合同:
{
"cause": {
"cause": null,"message": "not-null property references a null or transient value : com.xxx.xxx.model.Participation.contract"
},"message": "not-null property references a null or transient value : com.xxx.xxx.model.Participation.contract; nested exception is org.hibernate.PropertyValueException: not-null property references a null or transient value : com.xxx.xxx.model.Participation.contract"
}
我尝试了几种参与方式来引用合同,例如:
"contract": "http://localhost:8080/api/contracts/4"
没有运气。由于某种原因,系统会将字段留空,而不是使用在步骤1中创建的实体的前键。 我在做什么错了?
解决方法
问题可以通过以下方式解决:
- 添加新的存储库ParticipationRepository(扩展JpaRepository);
- 首先创建没有参与的合同:
POST http:// localhost:8080 / api / contracts {“ name”:“ Contract1”}
响应:
201 Created
{
"name": "Contract1","_links": {
"self": {
"href": "http://localhost:8080/api/contracts/3"
},"contract": {
"href": "http://localhost:8080/api/contracts/3"
},"participants": {
"href": "http://localhost:8080/api/contracts/3/participants"
}
}
}
- 创建一个参与并使用刚创建的合同中的URI来设置FK。假设联系人1已存在于数据库中。
POST http:// localhost:8080 / api / participations { “ clauses”:“ bla,bla,bla”, “ contract”:“ http:// localhost:8080 / api / contracts / 3”, “ contact”:“ http:// localhost:8080 / api / contacts / 1”}
响应:
201 Created
{
"clauses": "bla,bla,bla","_links": {
"self": {
"href": "http://localhost:8080/api/participations/5"
},"participation": {
"href": "http://localhost:8080/api/participations/5"
},"contract": {
"href": "http://localhost:8080/api/participations/5/contract"
},"contact": {
"href": "http://localhost:8080/api/contacts/5/contact"
}
}
}