非空属性引用瞬态值 - 瞬态实例必须在当前操作之前保存
Posted
技术标签:
【中文标题】非空属性引用瞬态值 - 瞬态实例必须在当前操作之前保存【英文标题】:Not-null property references a transient value - transient instance must be saved before current operation 【发布时间】:2013-10-05 03:20:26 【问题描述】:我有 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
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
任何帮助将不胜感激!
【问题讨论】:
【参考方案1】:我遇到了完全相同的问题。解决方案似乎是这样发送 JSON:
"firstname": "Tapas",
"lastname": "Jena",
"city": "Hyderabad",
"country": "id":"1"
我猜@RequestBody
尝试映射实体而不是单个字段,因为 Customer 实例正在引用 Country 实例。
(我有类似的两个实体,已加入。在数据库中,已创建引用实体(在您的情况下为国家)的记录,但使用 json 的实体创建(在您的情况下为客户)提供了相同的错误消息。对我来说 CascadeType.ALL 没有帮助,但 JSON 中的上述书面更改解决了问题。对于进一步的配置当然可以考虑 CascadeType。)
【讨论】:
【参考方案2】:我遇到了同样的错误,这就是我解决它的方法:
第一个实体:
@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));
【讨论】:
【参考方案3】:你应该改变:
@OneToOne(fetch = FetchType.EAGER)
@JoinColumn(name="COUNTRY_ID", nullable=false)
private Country country;
到:
@OneToOne(fetch = FetchType.EAGER)
@JoinColumn(name="COUNTRY_ID")
private Country country;
只需删除可为空的设置。
【讨论】:
您能否解释一下在这种情况下 nullable 是如何产生问题的?【参考方案4】:我遇到了类似的问题。两个实体:Document 和 Status。
Document 与 Status 有关系 OneToMany
,它代表 Document 所具有的Status 的历史记录。 p>
所以,在 Status 中有一个 @NotNull
@ManyToOne
Document 引用。
另外,我需要知道Document的实际Status。所以,我需要另一个关系,这次是@OneToOne
,也是@NotNull
,在Document中。
问题是:如果两个实体都有一个@NotNull
对另一个实体的引用,我如何才能在第一次持久化这两个实体?
解决方案是:从 actualStatus
引用中删除 @NotNull
引用。这样,它就能够持久化这两个实体。
【讨论】:
这并不能真正回答问题。如果您有其他问题,可以点击 进行提问。一旦你有足够的reputation,你也可以add a bounty 来引起对这个问题的更多关注。 我为我的问题提出了一个类似的解决方案。与新问题无关。【参考方案5】:试着把 CascadeType.ALL
@OneToOne(fetch = FetchType.EAGER,cascade=CascadeType.ALL)
@JoinColumn(name="COUNTRY_ID", nullable=false)
private Country country;
【讨论】:
好吧,那就做一件事。您的客户对象具有 ID 为 1 的国家/地区对象。但该国家/地区对象未处于持久状态。首先通过发送国家 ID 获取国家对象。将从数据库中检索到的国家对象设置为客户对象。然后保存客户对象。希望这次不会出错。 奇怪的是,CascadeType.ALL 对我有用,而这不起作用:@ManyToOne(cascade = CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH )
以上是关于非空属性引用瞬态值 - 瞬态实例必须在当前操作之前保存的主要内容,如果未能解决你的问题,请参考以下文章
Spring 和 Hibernate 错误——非空属性引用空值或瞬态值:com.tharaka.model.Employee.designation