JPA 尝试保存,如果不存在,请创建一个



你好,我正在尝试创建一个新用户,如果角色不存在,我希望这个用户创建一个,但不是说"角色不存在"。是@OneToMany关系,每个用户只有一个角色。我尝试过很多事情,当我设置cascade=CascadeType.REMOVE时,它会删除寄存器,但在设置cascade=CascadeType.ALL和保存时,它不会创建寄存器。我不明白为什么有人能解释我为什么?对不起我的英语。

@Entity
@Table(name = "users", uniqueConstraints = {
@UniqueConstraint(columnNames = {
"username"
}),
@UniqueConstraint(columnNames = {
"email"
})
})
public class User {
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
public User(String name, String username, String email, String password, Role role) {
super();
this.name = name;
this.username = username;
this.email = email;
this.password = password;
this.role = role;
}
public User() {
super();
// TODO Auto-generated constructor stub
}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
private String name;  
private String username;   
private String email; 
private String password;
@ManyToOne(cascade=CascadeType.ALL,fetch = FetchType.EAGER)
@JoinTable(name = "user_roles", 
joinColumns = @JoinColumn(name = "user_id"), 
inverseJoinColumns = @JoinColumn(name = "role_id"))
private Role role;
}


@Entity
@Table(name = "roles")
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
public Role(Long id, RoleName name) {
super();
this.id = id;
this.name = name;
}
@Enumerated(EnumType.STRING)
@NaturalId
@Column(length = 60)
private RoleName name;
public Role() {}
public Role(RoleName name) {
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public RoleName getName() {
return name;
}
public void setName(RoleName name) {
this.name = name;
}
}
Exception in thread "main" org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: relaciones.models.Role; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: relaciones.models.Role
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:278)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:223)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:527)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:153)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:135)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy87.save(Unknown Source)
at relaciones.services.CrearUsuario.createUsuario(CrearUsuario.java:17)
at relaciones.Relaciones.main(Relaciones.java:25)
Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: relaciones.models.Role
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:124)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:807)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:774)
at org.hibernate.jpa.event.internal.core.JpaPersistEventListener$1.cascade(JpaPersistEventListener.java:80)
at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:467)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:392)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:193)
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:126)
at org.hibernate.event.internal.AbstractSaveEventListener.cascadeBeforeSave(AbstractSaveEventListener.java:414)
at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:252)
at 


org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSav 
eEventListener.java:182)
at 



org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(Abs 
tractSaveEventListener.java:113)
at org.hibernate.jpa.event.internal.core.JpaPersistEventListener.saveWithGeneratedId(JpaPersistEventListener.java:67)
at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(Def 
aultPersistEventListener.java:189)
at 








org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:132)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:58)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:783)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:768)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:305)
at com.sun.proxy.$Proxy85.persist(Unknown Source)
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:490)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:377)
at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:200)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:641)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:605)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:590)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:59)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
... 11 more

两个实体之间的关系可能无效,一个可能的解决方案可能如下(对我来说有效(

@Entity
@Table(name = "user")
public class User{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Size(min = 1, max = 50)
@Column(length = 50, unique = true, nullable = false)
private String username;
@Size(min = 60, max = 60)
@Column(name = "password", length = 60, nullable = false)
private String password;
@Size(max = 50)
@Column(name = "name", length = 50)
private String name;
@Email
@Size(min = 5, max = 254)
@Column(length = 254, unique = true)
private String email;
@ManyToMany(cascade = CascadeType.MERGE, fetch = FetchType.EAGER)
@JoinTable(
name = "user_user_roles",
joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")},
inverseJoinColumns = {@JoinColumn(name = "role_id", referencedColumnName = "id")})
private Set<Role> roles =  new HashSet<>();
//getters and setters
}

和角色类

@Entity
@Table(name = "user_roles")
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(unique = true)
private String name;
//getters and setters
}

此外,在执行用户的插入操作之前,您的角色需要在数据库中

public User registerUser(UserDTO userDTO){
User newUser = new User();
String encryptedPassword = passwordEncoder.encode(password);
newUser.setUsername(userDTO.getUsername().toLowerCase());
newUser.setPassword(encryptedPassword);
newUser.setName(userDTO.getName());
newUser.setEmail(userDTO.getEmail().toLowerCase());       
Set<Role> roles = new HashSet<>();
//USER OR ADMIN role should be in db
roleRepository.findById("USER").ifPresent(roles::add);
newUser.setRoles(roles);
userRepository.save(newUser);
}

我在构造函数中找到了我正在设置id的解决方案,我制作了一个只有角色名称的解决方案并插入了service.createUsuario(new User("nacho", "user", "m@gmail.com", "123456", new Role(RoleName.ROLE_J)));谢谢

最新更新