Reputation: 4607
I have LoginCredential
class:
@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;
}
And here is my User
class:
@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;
}
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;
}
Now when I tried this command : curl -X POST -H "Content-Type: application/json" -d "{ \"email\": \"1\"}" http://localhost:8080/login
I get a LoginCredential
without any error, to be mentioned user
field is null
.
That's why I tried this command curl -X POST -H "Content-Type: application/json" -d "{ \"email\": \"1\",\"user\":{} }" http://localhost:8080/login
Which gives me error saying :
{ "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":.... }
Upvotes: 1
Views: 2085
Reputation: 14688
You have three problems
cascade
option to trigger User
entity creation from LoginCredential
save.@MapsId
annotation on User
so that they share the same id, otherwise LoginCredential
and its created User
will have different id values for both of them has @GeneratedValue(strategy = GenerationType.AUTO)
on their @Id
columnsTo 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;
}
and
@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);
Upvotes: 2
Reputation: 7624
You don't need @GeneratedValue
for User object
Add CascadeType
for OneToOne
By doing this you tell hibernate to save User to the database when saving LoginCredential
.
@Data
@Entity
public class LoginCredential implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
Long userID;
String eMail;
String passwordHash;
@OneToOne(cascade = {CascadeType.ALL}, mappedBy = "loginCredential", fetch = FetchType.LAZY)
User user;
}
Refer this for more detail
Upvotes: 0