Java Spring数据JPA分离实体传递给persist
我有两个实体用户和联系人详细信息。一个用户可以有多个联系人详细信息 还有一个UserService组件,负责持久化新用户。它检查ContactDetail是否存在,是否存在,并将该实体附加到新的用户实体,然后尝试保存它 User.javaJava Spring数据JPA分离实体传递给persist,java,spring,hibernate,jpa,spring-data,Java,Spring,Hibernate,Jpa,Spring Data,我有两个实体用户和联系人详细信息。一个用户可以有多个联系人详细信息 还有一个UserService组件,负责持久化新用户。它检查ContactDetail是否存在,是否存在,并将该实体附加到新的用户实体,然后尝试保存它 User.java public class User extends Base implements Resource<UUID>, UserDetails { private static final long serialVersionUID = 1L
public class User extends Base implements Resource<UUID>, UserDetails {
private static final long serialVersionUID = 1L;
@NotBlank
private String username;
@NotBlank
@Column(name = "first_name")
private String firstName;
@NotBlank
@Column(name = "last_name")
private String lastName;
@OneToMany(fetch = FetchType.EAGER, mappedBy = "user", cascade = { CascadeType.PERSIST, CascadeType.MERGE })
@Fetch(org.hibernate.annotations.FetchMode.SELECT)
private List<ContactDetail> contactdetails;
@Transient
public String email;
//bidirectional consistency
public void addContactDetail(ContactDetail contactDetail){
if(this.contactdetails == null){
this.contactdetails = new ArrayList<ContactDetail>();
}
if(!this.getContactDetails().contains(contactDetail)){
this.getContactDetails().add(contactDetail);
contactDetail.addUser(this);
}
}
看起来您的事务已中断,当您在一个事务中加载、在另一个事务中更改和保存时,会发生这种情况。验证是否正在使用TransactionSynchronizationManager的事务中运行save(User)Y Nadir您是对的。TransactionSynchronizationManager.isActualTransactionActive()返回false而不是true。save(user)方法顶部的批注:@Transactional(TxType.REQUIRES_NEW)未启动事务。我该如何解决这个问题?感谢这取决于您设置交易的方式。请看(在您的情况下,我想它将是@EnableTransactionManagement),感谢最低点的问题是UserService实际上是一个控制器。声明性事务需要一个服务类来启动事务。因此,我创建了一个用户服务类,将它注入到我的控制器中,并且它工作了。
public class ContactDetail extends Base implements Resource<UUID> {
@Column(name = "name")
private String name;
@Column(name = "type")
@Enumerated(EnumType.STRING)
private ContactType type;
@Column(name = "value", unique = true)
private String value;
@Column(name = "verified")
private boolean isVerified;
@Column(name = "created_date")
private Date createdDate;
@Column(name = "expired")
boolean isExpired;
@ManyToOne(fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST, CascadeType.MERGE })
@JoinColumn(name = "user_id", referencedColumnName = "id")
protected User user;
//bidirectional consistency
public void addUser(User user) {
if (this.getUser() == null) {
this.setUser(user);
user.addContactDetail(this);
}
}
@RestController
@RequestMapping("/api/v1/users")
public class UserService extends AbstractRestResource<User, UUID, User.UserWrapper> {
@Transactional(TxType.REQUIRES_NEW)
protected User save(User e) {
attachedContact(e);
User savedUser = repository().save(e);
return savedUser;
}
private void attachedContact(User u) {
ContactDetail contactDetail = contactDetailsRepository.findByTypeAndValue(ContactType.PRIMARY_EMAIL, u.getEmail());
if (contactDetail == null) {
contactDetail = new ContactDetail(u.getFirstName(), ContactType.PRIMARY_EMAIL, u.getEmail());
}
u.addContactDetail(contactDetail);
}
org.hibernate.PersistentObjectException: detached entity passed to persist: com.test.ContactDetail
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:139)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:801)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:794)
at org.hibernate.jpa.event.internal.core.JpaPersistEventListener$1.cascade(JpaPersistEventListener.java:97)
at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:350)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:293)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:161)