49

我有 2 个域模型和一个 Spring REST 控制器,如下所示:

@Entity
public class Customer{

@Id
private Long id;

@OneToOne(fetch = FetchType.EAGER)
@JoinColumn(name="COUNTRY_ID", nullable=false)
private Country country;

// other stuff with getters/setters

}

@Entity
public class Country{

@Id
@Column(name="COUNTRY_ID")
private Integer id;

// other stuff with getters/setters

}

弹簧 REST 控制器:

@Controller
@RequestMapping("/shop/services/customers")
public class CustomerRESTController {

   /**
    * Create new customer
    */
    @RequestMapping( method=RequestMethod.POST)
    @ResponseStatus(HttpStatus.CREATED)
    @ResponseBody
    public com.salesmanager.web.entity.customer.Customer createCustomer(@Valid @RequestBody   Customer customer, Model model, HttpServletRequest request, HttpServletResponse response) throws Exception {

        customerService.saveOrUpdate(customer);

        return customer;
    }

    // other stuff
}

我正在尝试使用以下 JSON 作为正文调用以上 REST 服务:

{
    "firstname": "Tapas",
    "lastname": "Jena",
    "city": "Hyderabad",
    "country": "1"
}

Country 表中已经存在国家代码 1。问题是当我调用此服务时出现以下错误:

org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.TransientPropertyValueException: Not-null property references a transient value - transient instance must be saved before current operation: com.test.model.Customer.country -> com.test.model.Country; nested exception is java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException: Not-null property references a transient value - transient instance must be saved before current operation: com.test.model.Customer.country -> com.test.model.Country

任何帮助将不胜感激!

4

5 回答 5

54

尝试把 CascadeType.ALL

@OneToOne(fetch = FetchType.EAGER,cascade=CascadeType.ALL)
@JoinColumn(name="COUNTRY_ID", nullable=false) 

private Country country;
于 2013-09-29T04:46:20.820 回答
15

我有一个类似的问题。两个实体:DocumentStatusDocumentOneToManyStatus有关系,它代表了 Document 具有的Status历史记录。

因此,在Status中有Document@NotNull @ManyToOne的引用。

另外,我需要知道Document的实际状态。所以,我需要另一个关系,这一次,也是在Document内部。@OneToOne@NotNull

@NotNull问题是:如果两个实体都引用另一个实体,我如何才能第一次持久化这两个实体?

解决方案是:@NotNull从参考中删除actualStatus参考。这样,它就能够持久化这两个实体。

于 2014-09-11T19:46:20.227 回答
1

我有同样的问题。解决方案似乎是像这样发送 JSON:

{
  "firstname": "Tapas",
  "lastname": "Jena",
  "city": "Hyderabad",
  "country": {"id":"1"}
}

我想@RequestBody尝试映射一个实体而不是单个字段,因为Customer实例正在引用一个Country实例。

(我有类似的两个实体,加入。在数据库中,已经创建了引用实体(在您的情况下为国家)的记录,但是使用 json 的实体创建(在您的情况下为客户)提供了相同的错误消息。对我来说 CascadeType .ALL 没有帮助,但 JSON 中的上述书面更改解决了问题。对于进一步的配置,当然可以考虑 CascadeType。)

于 2021-01-10T19:30:59.013 回答
0

我遇到了同样的错误,这就是我解决它的方法:

第一个实体:

    @Entity
    public class Person implements Serializable{
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private int personId;
        private String name;
        private String email;
        private long phoneNumber;
        private String password;
        private String userType;
        @OneToOne(fetch = FetchType.LAZY, mappedBy = "personCustomer", cascade 
        = CascadeType.ALL)
        private Customer customer;

第二实体:

@Entity
public class Customer implements Serializable{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int customerId;
    @OneToOne(fetch = FetchType.LAZY, optional = false, cascade = 
    CascadeType.ALL)
    @JoinColumn(name = "person_customer")
    @JsonIgnore
    private Person personCustomer;

我的控制器:

@PostMapping("/customer/registration")
    public PersonCustomer addCustomer(@RequestBody Person person)
    {
        Customer customer = new Customer(person);
        person.setCustomer(customer);
        Customer cust = customerRepo.save(customer);
        logger.info("{}", cust);
        Optional<Person> person_Cust = 
        personRepo.findById(cust.getPersonCustomer().getPersonId());
        Person personNew = person_Cust.get();
        PersonCustomer personCust = new PersonCustomer();

        if(cust.equals(null))
        {   
            personCust.setStatus("FAIL");
            personCust.setMessage("Registration failed");
            personCust.setTimestamp(personCust.timeStamp());
        }
        personCust.setStatus("OK");
        personCust.setMessage("Registration OK");
        personCust.setTimestamp(personCust.timeStamp());
        personCust.setPerson(personNew);

        return personCust;
    }

当我添加“person.setCustomer(customer);”时,问题就解决了。由于两个 POJO 类都有相互引用,因此我们必须在使用 JPA 存储库方法之前“设置”相互引用(customerRepo.save(customer));

于 2020-02-12T07:03:34.237 回答
-2

你应该改变:

@OneToOne(fetch = FetchType.EAGER)
@JoinColumn(name="COUNTRY_ID", nullable=false)
private Country country;

至 :

@OneToOne(fetch = FetchType.EAGER)
@JoinColumn(name="COUNTRY_ID")
private Country country;

只需删除可为空的设置。

于 2018-04-20T10:20:27.443 回答