Spring Boot中的TransientPropertyValueException [英] TransientPropertyValueException in Spring Boot
问题描述
我有LoginCredential
课:
@Data
@Entity
public class LoginCredential implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
Long userID;
String eMail;
String passwordHash;
@GeneratedValue(strategy = GenerationType.AUTO)
@OneToOne(mappedBy = "loginCredential", fetch = FetchType.LAZY)
User user;
}
这是我的User
课:
@Data
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
Long userID;
@OneToOne(fetch = FetchType.LAZY,targetEntity = LoginCredential.class)
@JoinColumn(name = "userID",referencedColumnName = "userID")
private LoginCredential loginCredential;
}
而我的LoginCredentialController
的 POST -ing方法很简单:
And my LoginCredentialController
's POST-ing method is simple :
@PostMapping("/login")
LoginCredential newLoginCredential(@RequestBody LoginCredential newLoginCredential) {
logger.debug(newLoginCredential);
LoginCredential a=repository.save(newLoginCredential);
logger.debug(a);
return a;
}
现在,当我尝试此命令时:curl -X POST -H "Content-Type: application/json" -d "{ \"email\": \"1\"}" http://localhost:8080/login
Now when I tried this command : curl -X POST -H "Content-Type: application/json" -d "{ \"email\": \"1\"}" http://localhost:8080/login
我得到的LoginCredential
没有任何错误,要提到的user
字段是null
.
I get a LoginCredential
without any error, to be mentioned user
field is null
.
这就是为什么我尝试此命令curl -X POST -H "Content-Type: application/json" -d "{ \"email\": \"1\",\"user\":{} }" http://localhost:8080/login
That's why I tried this command curl -X POST -H "Content-Type: application/json" -d "{ \"email\": \"1\",\"user\":{} }" http://localhost:8080/login
哪个让我出错:
{
"status" : 500,
"error" : "Internal Server Error",
"message" : "org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : com.mua.cse616.Model.LoginCredential.user -> com.mua.cse616.Model.User; org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : com.mua.cse616.Model.LoginCredential.user -> com.mua.cse616.Model.User",
"trace":....
}
推荐答案
您遇到三个问题
- 缺少
cascade
选项可从LoginCredential
保存触发User
实体创建. -
User
上缺少@MapsId
注释,因此它们共享相同的id,否则LoginCredential
及其创建的User
将具有不同的id值,因为它们在@Id
列上均具有@GeneratedValue(strategy = GenerationType.AUTO)
- 未设置双方关系...
- Lacking a
cascade
option to triggerUser
entity creation fromLoginCredential
save. - Lacking
@MapsId
annotation onUser
so that they share the same id, otherwiseLoginCredential
and its createdUser
will have different id values for both of them has@GeneratedValue(strategy = GenerationType.AUTO)
on their@Id
columns - Not setting both sides of the relationship...
要解决所有将实体更改为下面的问题(我还删除了一些无用的注释和值);
To fix all you need to change your entities to below (I also removed some useless annotations and values);
@Data
@Entity
public class User {
@Id
Long userID;
@JsonBackReference
@MapsId
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "userID", referencedColumnName = "userID")
@ToString.Exclude
private LoginCredential loginCredential;
}
和
@Data
@Entity
public class LoginCredential {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Long userID;
String eMail;
String passwordHash;
@JsonManagedReference
@OneToOne(mappedBy = "loginCredential", fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
private User user;
}
在最终确定端点之前,还需要设置关系的两面;
Also need to set both sides of the relationship before finalizing your endpoint;
Optional.ofNullable(loginCredential.getUser())
.ifPresent(user -> user.setLoginCredential(loginCredential));
loginCredentialRepo.save(loginCredential);
这篇关于Spring Boot中的TransientPropertyValueException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!