I have two entities, user:
@Data
@EqualsAndHashCode(exclude = "id")
@Entity
@Table(name = "users")
public class User {
@Id
@SequenceGenerator(name = "user_id_seq_gen", sequenceName = "users_id_seq", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_id_seq_gen")
private long id;
@Column(nullable = false, unique = true, length = 100)
@NotNull
@Length(min = 4, max = 100)
private String email;
@Column(nullable = false, length = 50)
@NotNull
@Length(min = 6, max = 100)
private String password;
}
And verification:
@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
public class Verification {
@Id
@Column(length = 20)
private String code;
@OneToOne(cascade = {CascadeType.PERSIST})
private User user;
}
And I save these entities in this method:
@Transactional
public void registerUser(User user) {
user.setPassword(DigestUtils.md5Hex(user.getPassword()));
String code = RandomStringUtils.random(20, true, true);
Verification verification;
while(true) {
if (!verificationRepository.existsByCode(code)) {
verification = new Verification(code, user);
break;
} else {
code = RandomStringUtils.random(20, true, true);
}
}
verificationRepository.save(verification);
}
But CascadeType persist doesn't work, it throws the following exception:
org.postgresql.util.PSQLException: ERROR: null value in column "user_id" violates not-null constraint
Подробности: Failing row contains (Oda2AolKrQXYSxuVmclO, null).
But when I change cascade type to MERGE, it works. And I don't understand why, because I create new User and new Verification at the same time. And first I need to save the user, then the verification. Do you know the answer?
Spring Data JPA uses the ID to determine if the instance is new or not. Since it seems you are setting the id to a non-null value Spring Data JPA considers it an existing entity and calls merge instead of persist.
Read "Saving Entities" in the Reference Documentation about how to tweak that behavior.
I recommend thinking in terms of Domain Driven Design and Aggregates/Aggregate Roots in order to determine the entities which should be linked via Cascade.ALL + DELETE_ORPHAN and those without any cascading and separate repositories instead.
I recommend reading "Advancing Enterprise DDD" about the topic.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With