2014-04-16 4 views
1

Я переношу свое приложение из сопоставления на основе xml на сопоставление на основе аннотаций JPA. Но это происходит только в простом случае. Например, у меня есть следующие 3 сущности:@OneToMany Аннотации JPA вызывают ненужное обновление sql и не каскадируют

@Entitiy 
public class UserAccount { 

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) 
    @JoinColumn(name = "user_account_id", nullable = false, 
       insertable = true, updatable = false) 
    @NotNull 
    private Set<Authority> authorities; 

    @OneToOne(cascade = CascadeType.ALL) 
    @JoinColumn(name="USER_ID", nullable = false) 

    ... get and setter 
} 

@Entity 
public class Authority { 

    @Column 
    private String authority; 

    ... get and setter 
} 

@Entity 
public class User { 
    ... some properties 
} 

Если я создаю новый экземпляр UserAccount и попытаться спасти его, я получил исключение, поскольку экземпляр органа не был сохранен, а это значит, что Безразлично Каскад, как он должен был делать.

org.springframework.dao.InvalidDataAccessApiUsageException: 
org.hibernate.TransientObjectException: object references an unsaved transient 
instance - save the transient instance before flushing: Authority ... 

Это происходит потому, что спящий режим пытается обновить строку органа (который не был вставлен до того):

Hibernate: 
    insert into users ... 

Hibernate: 
    insert into user_accounts ... 

Hibernate: 
    update authorities set user_account_id=? where id=? 

я использовал следующие услуги для сохранения UserAccount экземпляра.

@Service 
public class UserAccountService { 

    @Resource 
    private UserAccountRepository userAccountRepository; 

    @Transactional(propagation = Propagation.REQUIRED, readOnly = false) 
    public void save(UserAccount userAccount) { 

     userAccountRepository.save(userAccount); 
    } 

} 

Странная вещь, что экземпляр пользователя будет сохранен, поэтому отображение каскады OneToOne (если удалить свойство UserAccount.authorities). Но это сработало с отображением на основе xml (и без JPA). В итоге я вызвал отдельный метод хранения экземпляров Authoriy.

@Service 
public class UserAccountService { 

    @Resource 
    private UserAccountRepository userAccountRepository; 
    @Resource 
    private AuthorityRepository authorityRepository; 

    @Transactional(propagation = Propagation.REQUIRED, readOnly = false) 
    public void save(UserAccount userAccount) { 

     userAccountRepository.save(userAccount); 
     authorityRepository.save(userAccount.getAuthoritiesSet()); 
    } 

} 

Это значит, я каскад вручную ... Однако, глядя в выполненных инструкции SQL, я могу видеть, что спящий режим вставляет экземпляр полномочий и после этого, он обновляет эту строку, чтобы установить ссылку UserAccount:

Hibernate: 
    insert into users ... 

Hibernate: 
    insert into user_accounts ... 

Hibernate: 
    insert into authorities (authority) values (?) 

Hibernate: 
    update authorities set user_account_id=? where id=? 

И для меня это проблема с производительностью, потому что есть много полномочий, и я не хочу иметь 20 вставок и после этого 20 обновлений. Но я не смог «удалить» обновления и сообщить в спящий режим, чтобы установить user_account_id вместе с полномочием.

Поскольку у меня много других объектов, имеющих отношения OneToMany, я очень заинтересован в решении этой проблемы и ценю вашу помощь и мысли.

Hibernate: 4.3.4.Final, пружинные данных JPA: 1.5.1.RELEASE

С наилучшими пожеланиями, Daniel

ответ

0

"... объект ссылается на несохраненные переходных ..." означает, что вы сопоставили дочерний объект с родителем, а ребенок еще не сохранен до сохранения родителя.

В вашем случае вы сохраняете родитель UserAccount вместе с дочерней сущностью Власть перед сохранением органов.

Вы можете создать отношение OneToMany для властей с соответствующим Cascade.

@OneToMany(cascade = CascadeType.ALL) 
private Set<Authority> authorities; 

И если у вас есть правильный каскад, вам не нужно сохранять полномочия отдельно, как показано ниже. Вы можете удалить его.

authorityRepository.save(userAccount.getAuthoritiesSet()); 
+0

Привет, Джей, но это именно то, что я уже сделал (загляните в мой объект UserAccount). Это действительно странно. – Phillip

+0

Хорошо попробуйте удалить все сопоставления parent/child и добавить один за другим и проверить, где проблема. – Jay

0

Я решил обе проблемы, понизив версию спящего режима до версии 4.2.11.Final.Я не знаю, почему эти проблемы возникают в 4.3.4. Возможно, это проблема во всех версиях версии 4.3.x!

+0

- это решение проблемы? В настоящее время я сталкиваюсь с аналогичными проблемами. – EasterBunnyBugSmasher

+0

Да. Я еще не пытался обновить до 4.3.5. – Phillip

0

У меня была очень похожая проблема с отображением ManyToOne. Устранена проблема, добавив значение по умолчанию в поле версии.

@Version 
@Column(name = "VERSION") 
private Integer version = 1; 
Смежные вопросы