无法在Spring Data REST请求中保存OneToMany / ManyToOne关系

问题描述

我正在使用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> {
}

要保存有几个参与者的新合同,我在邮递员中进行下一步:

  1. 创建合同并获取其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. 到目前为止一切顺利。既然合同已经生效,我将添加参与者: 联系人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中创建的实体的前键。 我在做什么错了?

解决方法

问题可以通过以下方式解决:

  1. 添加新的存储库ParticipationRepository(扩展JpaRepository);
  2. 首先创建没有参与的合同:

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"
    }
  }
}
  1. 创建一个参与并使用刚创建的合同中的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"
    }
  }
}

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...