2016-04-24 3 views
1

Я следующие два объекта:отдельностоящий объект передается упорствовать: Профиль

@Entity 
public class Profile implements Serializable { 

    private static final long serialVersionUID = 1L; 

    @Id 
    @GeneratedValue 
    private int id; 

    @OneToOne 
    @JoinColumn(nullable = false, name = "USERNAME_FK") 
    private RegisteredUser user; 

    ... 

и

@Entity 
public class RegisteredUser implements Serializable { 

    private static final long serialVersionUID = 1L; 

    @Id 
    private int id; 

    @OneToOne 
    @JoinColumn(nullable = false, name = "USERNAME_FK") 
    private User user; 

    @OneToOne(cascade = CascadeType.ALL, mappedBy = "user") 
    private Profile profile; 
    ... 

Я использую «хранилищам» и спящий режим для хранения объектов в базе данных. Я бы хотел, чтобы мои сущности были максимально надежными, используя аннотации, но это только вызывает у меня массу проблем.

В настоящее время, у меня следующий код:

@Autowired 
private RegisteredUserRepository rur; 

@Autowired 
private UserRepository ur; 
... 

// Creating a user 
User root = new User("root", "1234", "[email protected]"); 
root.setFirstName("root"); 
root.setLastName("root"); 
root = ur.save(root); 

Profile profile = new Profile(String.format("%s", root.getFullName())); 

RegisteredUser registeredUser = new RegisteredUser(profile); 
root.setRegisteredUser(registeredUser); 
registeredUser = rur.save(registeredUser); 
registeredUser = rur.save(registeredUser); // PROBLEM HERE! 

отладочные задачи является:

Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: com.mycompany.app.models.Profile 
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:139) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:801) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:794) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.jpa.event.internal.core.JpaPersistEventListener$1.cascade(JpaPersistEventListener.java:97) ~[hibernate-entitymanager-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:350) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:293) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:161) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:118) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.event.internal.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:470) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:295) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:195) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:138) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.jpa.event.internal.core.JpaPersistEventListener.saveWithGeneratedId(JpaPersistEventListener.java:84) ~[hibernate-entitymanager-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:206) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:149) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:75) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:811) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:784) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:789) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:1181) ~[hibernate-entitymanager-4.3.11.Final.jar:4.3.11.Final] 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_40] 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_40] 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_40] 
    at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_40] 
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:294) ~[spring-orm-4.2.5.RELEASE.jar:4.2.5.RELEASE] 
    at com.sun.proxy.$Proxy88.persist(Unknown Source) ~[na:na] 
    at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:439) ~[spring-data-jpa-1.9.4.RELEASE.jar:na] 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_40] 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_40] 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_40] 
    at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_40] 
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:483) ~[spring-data-commons-1.11.4.RELEASE.jar:na] 
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:468) ~[spring-data-commons-1.11.4.RELEASE.jar:na] 
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:440) ~[spring-data-commons-1.11.4.RELEASE.jar:na] 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.5.RELEASE.jar:4.2.5.RELEASE] 
    at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:61) ~[spring-data-commons-1.11.4.RELEASE.jar:na] 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.5.RELEASE.jar:4.2.5.RELEASE] 
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) ~[spring-tx-4.2.5.RELEASE.jar:4.2.5.RELEASE] 
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281) ~[spring-tx-4.2.5.RELEASE.jar:4.2.5.RELEASE] 
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) ~[spring-tx-4.2.5.RELEASE.jar:4.2.5.RELEASE] 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.5.RELEASE.jar:4.2.5.RELEASE] 
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136) ~[spring-tx-4.2.5.RELEASE.jar:4.2.5.RELEASE] 
    ... 21 common frames omitted 

То, что я пытался достичь в том, что, когда я пытаюсь сохранить во второй раз зарегистрированный пользователь, он правильно обновит таблицы.

Как я могу решить эту проблему? Я видел, что это может быть из-за того, как я реализовал сеттеров и добытчиками, так что они:

геттеры и сеттеры в классе RegisteredUser:

public Profile getProfile() { 
    return profile; 
} 

public void setProfile(Profile profile) { 
    if (sameAsFormer(profile)) { 
     return; 
    } 

    Profile oldProfile = this.profile; 
    this.profile = profile; 

    if (oldProfile != null) { 
     oldProfile.setRegisteredUser(null); 
    } 

    if (this.profile != null) { 
     this.profile.setRegisteredUser(this); 
    } 
} 

сеттеров и добытчиками в Profile:

ответ

2

Генератор идентификаторов не указан для объекта RegisteredUser, что означает, что стратегия генерации assigned (перед сохранением необходимо указать значение id).

Поскольку вы не указываете значение id, экземпляр registeredUser считается второстепенным во втором звонке save. Операция Persist каскадируется с ассоциированным Profile, который уже был сохранен при первом вызове с правильно настроенным идентификатором (он содержит @GeneratedValue аннотация в поле id) и поэтому считается отсоединенным в новой транзакции.

Самым простым решением является определение генератора ID для RegisteredUser, а также:

@Id 
@GeneratedValue 
private int id; 
+0

Спасибо, что, кажется, решить эту проблему. Я не знал об этом ... – nbro

+0

Извините, чувак, у меня есть еще одна проблема, если вы можете помочь. В той же ситуации, что и выше, я пытаюсь удалить «RegisteredUser», но он ничего не удаляет ... что может быть проблемой? – nbro

+0

[Этот ответ] (http://stackoverflow.com/a/34843369/4754790) может быть полезен. –

Смежные вопросы