Not-null属性引用瞬态值 - 必须在当前操作之前保存瞬态实例

时间:2013-09-29 04:05:56

标签: java json spring hibernate rest

我有两个域模型和一个Spring REST Controller,如下所示:

@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

}

Spring 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"
}

国家/地区代码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

任何帮助将不胜感激!

5 个答案:

答案 0 :(得分:40)

尝试使用CascadeType.ALL

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

private Country country;

答案 1 :(得分:12)

我有类似的问题。两个实体:文档状态文档的关系OneToMany状态,表示文档状态的历史记录。

因此,状态中有<{1>} @NotNull 文档的参考。

另外,我需要知道文档的实际状态。所以,我需要另一种关系,这次@ManyToOne,还有@OneToOne,在文档中。

问题是:如果两个实体都有@NotNull引用另一个,我怎么能第一次坚持这两个实体呢?

解决方案是:从@NotNull引用中删除@NotNull引用。通过这种方式,它能够持久保存两个实体。

答案 2 :(得分:1)

你应该改变:

Header

到:

UIScrollView

只需删除可空设置。

答案 3 :(得分:1)

我遇到了完全相同的问题。解决方案似乎是像这样发送 JSON:

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

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

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

答案 4 :(得分: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))之前,我们必须“设置”彼此的引用。