Я переношу свое приложение из сопоставления на основе 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
Привет, Джей, но это именно то, что я уже сделал (загляните в мой объект UserAccount). Это действительно странно. – Phillip
Хорошо попробуйте удалить все сопоставления parent/child и добавить один за другим и проверить, где проблема. – Jay