简体   繁体   English

当我第一次检索必须在 @ManyToMany 关系中使用的对象时,为什么会获得这个“传递给持久化的分离实体”?

[英]Why am I obtaining this "detached entity passed to persist" when I first retrieve the object that has to be used in a @ManyToMany relationship?

I am working on a Spring Boot project using Spring Data JPA.我正在使用 Spring Data JPA 处理 Spring Boot 项目。 I am pretty new in Hibernate mapping and I have the following doubts.我在 Hibernate 映射方面很新,我有以下疑问。

NOTE: I first implemented my DB tables, then I am mapping these tables into Java entity classes.注意:我首先实现了我的数据库表,然后我将这些表映射到 Java 实体类。

I have this User class:我有这个用户类:

@Entity
@Table(name = "portal_user")
@Getter
@Setter
public class User implements Serializable {
     
    private static final long serialVersionUID = 5062673109048808267L;
    
    @Id
    @Column(name = "id")
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int id;
    
    @Column(name = "first_name")
    private String firstName;
    
    @Column(name = "middle_name")
    private String middleName;
    
    @Column(name = "surname")
    private String surname;
    
    @Column(name = "sex")
    private char sex;
    
    @Column(name = "birthdate")
    private Date birthdate;
    
    @Column(name = "tex_code")
    private String taxCode;
    
    @Column(name = "e_mail")
    private String eMail;
    
    @Column(name = "contact_number")
    private String contactNumber;
    
    @Temporal(TemporalType.DATE)
    @Column(name = "created_at")
    private Date createdAt;
    
    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "user", orphanRemoval = true)
    @JsonManagedReference
    private Set<Address> addressesList = new HashSet<>();
    
    //@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
    //@JsonManagedReference
    //private Set<User_UserType> userToUserTypeAssociation = new HashSet<>();
    
    @ManyToMany(cascade = { CascadeType.ALL })
    @JoinTable(
        name = "portal_user_user_type", 
        joinColumns = { @JoinColumn(name = "portal_user_id_fk") }, 
        inverseJoinColumns = { @JoinColumn(name = "user_type_id_fk") }
    )
    //Set<UserType> userTypes;
    List<UserType> userTypes;


    public User(String firstName, String middleName, String surname, char sex, Date birthdate, String taxCode,
            String eMail, String contactNumber, Date createdAt) {
        super();
        this.firstName = firstName;
        this.middleName = middleName;
        this.surname = surname;
        this.sex = sex;
        this.birthdate = birthdate;
        this.taxCode = taxCode;
        this.eMail = eMail;
        this.contactNumber = contactNumber;
        this.createdAt = createdAt;
    }
        

}

as you can see it contains this **@ManyToMany relationshipt based on the portal_user_user_type association table:如您所见,它包含基于portal_user_user_type关联表的 **@ManyToMany 关系:

@ManyToMany(cascade = { CascadeType.ALL })
@JoinTable(
    name = "portal_user_user_type", 
    joinColumns = { @JoinColumn(name = "portal_user_id_fk") }, 
    inverseJoinColumns = { @JoinColumn(name = "user_type_id_fk") }
)
//Set<UserType> userTypes;
List<UserType> userTypes;

This is my UserType entity classes mapping the user_type DB table:这是我映射user_type数据库表的UserType实体类:

@Entity
@Table(name = "user_type")
@Getter
@Setter
public class UserType implements Serializable {
    
    private static final long serialVersionUID = 6904959949570501298L;

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private int id;
    
    @Column(name = "type_name")
    private String typeName;
    
    @Column(name = "description")
    private String description;
    
    @OneToMany(mappedBy = "userType")
    @JsonManagedReference
    private Set<User_UserType> userToUserTypeAssociation = new HashSet<>();
    

    public UserType() {
        super();
        // TODO Auto-generated constructor stub
    }
    
    public UserType(String typeName, String description) {
        super();
        this.typeName = typeName;
        this.description = description;
    }

}

Then I created this JUnit test method:然后我创建了这个 JUnit 测试方法:

@SpringBootTest()
@ContextConfiguration(classes = GetUserWsApplication.class)
@TestMethodOrder(OrderAnnotation.class)
public class UserRepositoryTest {
    
    @Autowired
    private UsersRepository userRepository;
    
    @Autowired 
    UserTypeRepository userTypeRepository;
    
    @Test
    @Order(1)
    public void testInsertUser() {
        
        User user = new User("Luca", null, "Verdi", 'M', new Date(), "XXX", "xxx@gmail.com", "329123456", new Date());
        
        Set<Address> addressesList = new HashSet<>();
        addressesList.add(new Address("Italy", "RM", "00100", "Via XXX 123", "near YYY", user));
        
        user.setAddressesList(addressesList);
        
        //List<UserType> userTypesList = userTypeRepository.findAll();
        List<UserType> userTypesList = new ArrayList<UserType>();

        //Set<UserType> userTypesList = new HashSet<>();
        UserType userType1 = new UserType("ADMIN", "Admin user type !!!");
        UserType userType2 = new UserType("USER", "Just a simple user...");
        
        userTypesList.add(userType1);
        userTypesList.add(userType2);
        
        //user.setUserToUserTypeAssociation(user_UserType_List);
        user.setUserTypes(userTypesList);
        
        userRepository.save(user);
        assertTrue(true);
        
    }
    
}

Running this test method it works as I expected.运行此测试方法,它按我的预期工作。 Basically it inserted a new record into the portal_user table (mapped by my User entity class), then it inserted a record into the user_type table (mapped by the UserType entity class) and also it inserted the relationship into my Many To many association table named portal_user_user_type ).基本上,它将一条新记录插入到portal_user表中(由我的User实体类映射),然后将一条记录插入到user_type表中(由UserType实体类映射),并将关系插入到名为“多对多”的关联表中portal_user_user_type )。

Ok, now I have the following situation.好的,现在我有以下情况。 The user_type table mapped by the UserType class is a typological table. UserType类映射的user_type表是一个类型表。 It contains the predefined information related the possible user types (such as: "ADMIN", "MODERATOR", "USER", etcetc).它包含与可能的用户类型(例如:“ADMIN”、“MODERATOR”、“USER”等)相关的预定义信息。

So this table must be pre populated and I have not to insert new records into this table but I have to use the existing record to populate my portal_user_user_type association table when a new user is created.所以这个表必须预先填充,我不必在这个表中插入新记录,但我必须在创建新用户时使用现有记录来填充我的portal_user_user_type关联表。

So my idea was the following one:所以我的想法是以下一个:

  1. I first retrieve the list of possible UserType instances via a JPA repository.我首先通过 JPA 存储库检索可能的 UserType 实例列表。
  2. Differently from the previous code, instead to create these UserType instances I set this list into my user object.与之前的代码不同,为了创建这些UserType实例,我将此列表设置到我的用户对象中。

I don't know if this is the correct strategy.我不知道这是否是正确的策略。 Anyway I have changed the previous code of my unit test method in this way and I am obtaining some problems:无论如何,我以这种方式更改了我的单元测试方法的先前代码,并且遇到了一些问题:

@SpringBootTest()
@ContextConfiguration(classes = GetUserWsApplication.class)
@TestMethodOrder(OrderAnnotation.class)
public class UserRepositoryTest {
    
    @Autowired
    private UsersRepository userRepository;
    
    @Autowired 
    UserTypeRepository userTypeRepository;
    
    
    @Test
    @Order(1)
    public void testInsertUser() {
        
        User user = new User("Luca", null, "Verdi", 'M', new Date(), "XXX", "xxx@gmail.com", "329123456", new Date());
        
        Set<Address> addressesList = new HashSet<>();
        addressesList.add(new Address("Italy", "RM", "00100", "Via XXX 123", "near YYY", user));
        
        user.setAddressesList(addressesList);
        
        List<UserType> userTypesList = userTypeRepository.findAll();
        
        user.setUserTypes(userTypesList);
        
        userRepository.save(user);
        assertTrue(true);
        
    }
    
}

As you can see I am first retrieving the user types list by this JPA repository, then I am setting this list (instead the one that I manually created in the previous version of the test method):如您所见,我首先通过此 JPA 存储库检索用户类型列表,然后设置此列表(而不是我在先前版本的测试方法中手动创建的列表):

List<UserType> userTypesList = userTypeRepository.findAll();
user.setUserTypes(userTypesList);

The retrieved user type is something like this (this list was retrieved by my userTypeRepository.findAll() call):检索到的用户类型是这样的(这个列表是通过我的userTypeRepository.findAll()调用检索的):

在此处输入图片说明

So I set it using the setUserTypes() method (as I have done before with the UserType object that was manually created).所以我使用setUserTypes()方法设置它(就像我之前使用手动创建的 UserType 对象所做的那样)。

The problem is that when this line is executed:问题是当这一行被执行时:

userRepository.save(user);

I obtain the following exception:我得到以下异常:

Hibernate: 
    insert 
    into
        portal_user
        (birthdate, contact_number, created_at, e_mail, first_name, middle_name, sex, surname, tex_code) 
    values
        (?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate: 
    insert 
    into
        address
        (country, notes, province, street, fk_user_id, zip_code) 
    values
        (?, ?, ?, ?, ?, ?)

org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: com.easydefi.users.entity.UserType; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: com.easydefi.users.entity.UserType
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:297)
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:233)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:551)
    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:152)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:174)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215)
    at jdk.proxy2/jdk.proxy2.$Proxy105.save(Unknown Source)
    at com.easydefi.users.tests.RepositoryTests.UserRepositoryTest.testInsertUser(UserRepositoryTest.java:77)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:78)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:567)
    at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:688)
    at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
    at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
    at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:210)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:206)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:131)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:65)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:108)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:96)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:84)
    at org.eclipse.jdt.internal.junit5.runner.JUnit5TestReference.run(JUnit5TestReference.java:98)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:40)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:529)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:756)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:452)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)
Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: com.easydefi.users.entity.UserType
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:120)
    at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:110)
    at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:744)
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:712)
    at org.hibernate.engine.spi.CascadingActions$7.cascade(CascadingActions.java:298)
    at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:499)
    at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:423)
    at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:220)
    at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:532)
    at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:463)
    at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:426)
    at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:220)
    at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:153)
    at org.hibernate.event.internal.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:459)
    at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:293)
    at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:193)
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:123)
    at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:185)
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:128)
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:55)
    at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:99)
    at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:720)
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:706)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:78)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:567)
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:311)
    at jdk.proxy2/jdk.proxy2.$Proxy102.persist(Unknown Source)
    at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:597)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:78)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:567)
    at org.springframework.data.repository.core.support.RepositoryMethodInvoker$RepositoryFragmentMethodInvoker.lambda$new$0(RepositoryMethodInvoker.java:289)
    at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:137)
    at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:121)
    at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:529)
    at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:285)
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:599)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:163)
    at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:138)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:80)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137)
    ... 75 more

The problems seems to be this detached entity passed to persist but what it means?问题似乎是这个分离的实体传递给了持久化,但这意味着什么?

How can I try to fix this issue?我该如何尝试解决这个问题? and what could be a good approach to first retrieve the list of the possible UserTypes and then to insert a new User with the relation with these retrieved user types avoiding to inser them again in the DB?什么是首先检索可能的UserTypes列表,然后插入一个与这些检索到的用户类型相关的新 User 避免在数据库中再次插入它们的好方法?

This looks like a problem with Cascade type you are using.这看起来像是您使用的 Cascade 类型的问题。 Here you are setting the cascade type to CascadeType.ALL在这里,您将级联类型设置为CascadeType.ALL

@ManyToMany(cascade = { CascadeType.ALL })
@JoinTable(
    name = "portal_user_user_type", 
    joinColumns = { @JoinColumn(name = "portal_user_id_fk") }, 
    inverseJoinColumns = { @JoinColumn(name = "user_type_id_fk") }
)
//Set<UserType> userTypes;
List<UserType> userTypes;

Why this is a bad idea?为什么这是一个坏主意? When you do a CascadeType.ALL on the child entity, it will cause every DB operation to be propagated to the entity UserType.当您在子实体上执行CascadeType.ALL时,它会导致每个数据库操作传播到实体 UserType。 Since Transaction is PERSISTED, it tries to PERSIST UserType as well and that doesn't work since UserType already is in the db.由于 Transaction 是 PERSISTED,它也尝试 PERSIST UserType 并且这不起作用,因为 UserType 已经在数据库中。 To fix this use CascadeType.MERGE instead as with it the UserType will be automatically merged instead.要解决此问题,请改用CascadeType.MERGE ,因为 UserType 将改为自动合并。 So change this line:所以改变这一行:

@ManyToMany(cascade = { CascadeType.MERGE})

Also as a side note, I assume UserType entities are unique?另外作为旁注,我假设 UserType 实体是唯一的? So consider using set instead of list for storing them, as you do not want duplicates.所以考虑使用 set 而不是 list 来存储它们,因为你不想要重复。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 “分离的实体传递给持久化”当我尝试持久化具有多对多关系的实体时 - “detached entity passed to persist” When i try to persist an Entity with ManyToMany relationship 通过获取分离实体以保持@ManyToMany双向关系 - Getting detached entity passed to persist with @ManyToMany bidirectional relationship Spring 数据 JPA 和 hibernate 分离的实体传递以保持多对多关系 - Spring data JPA and hibernate detached entity passed to persist on ManyToMany relationship 当组合键与实体一起使用时,分离的实体传递以持久化 - detached entity passed to persist when Composite key used with entity 分离的实体传递给持久对象:一对一关系 - detached entity passed to persist: one to one to relationship 尝试持久化分离对象时,关于“传递给持久化的分离实体”异常的异常行为? - Unusual behavior regarding "detached entity passed to persist" exception when trying to persist a detached object? 有没有办法将分离的对象传递给JPA持久化? (传递给持久化的分离实体) - Is there a way to pass detached object to JPA persist? (detached entity passed to persist) org.hibernate.PersistentObjectException:分离的实体传递给持久化-ManyToMany映射 - org.hibernate.PersistentObjectException: detached entity passed to persist - ManyToMany Mapping 带有CascadeType.ALL的ManyToMany导致传递的Detched实体持久化 - ManyToMany with CascadeType.ALL results in Detached entity passed to persist 我想知道&#39;分离的实体传递给持久&#39;的原因发生了 - I wonder the reason 'detached entity passed to persist' happens
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM