Я давно хотел обновить это, но был слишком занят ...
Хорошо, получается, что это не возможно с JPA.
Тем не менее, есть обходной путь.
Ранее я упоминал, что класс Document выглядит следующим образом.
@Entity
@Table(name = "DOCUMENT")
public class Document implements java.io.Serializable {
@Id
@Column(name = "DOC_ID", nullable = false)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator =
"DocIdSeq")
@SequenceGenerator(name = "DocIdSeq", sequenceName = "DOC_ID_SEQ", allocationSize = 1)
private Long docId;
}
Это была только сокращенная версия, чтобы прояснить проблему.
В реальном классе есть коллекция разделов:
@Entity
@Table(name = "DOCUMENT")
public class Document implements java.io.Serializable {
@Id
@Column(name = "DOC_ID", nullable = false)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator =
"DocIdSeq")
@SequenceGenerator(name = "DocIdSeq", sequenceName = "DOC_ID_SEQ", allocationSize = 1)
private Long docId;
@OneToMany
private Set<Section> sections = new HashSet<Section>(0);
}
Если бы у Секции был простой первичный ключ, JPA легко обработал бы отношение, поскольку он принял бы идентификатор из приложения или сгенерировал бы его из последовательности, но он не будет делать оба с одним идентификатором.
Итак, решение состоит в том, чтобы самостоятельно управлять отношениями и добавить функцию жизненного цикла:
@Entity
@Table(name = "DOCUMENT")
public class Document implements java.io.Serializable {
@Id
@Column(name = "DOC_ID", nullable = false)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator =
"DocIdSeq")
@SequenceGenerator(name = "DocIdSeq", sequenceName = "DOC_ID_SEQ", allocationSize = 1)
private Long docId;
@Transient
private Set<Section> sections = new HashSet<Section>(0);
@PostPersist
public void updateChildIds() {
for (Section section : this.sections) {
section.getId().setDocId(this.docId);
}
}
}
Как вы можете видеть, отношение Секции теперь является Переходным, что означает, что JPA не будет управлять им.
После сохранения документа, платформа вызовет функцию updateChildIds, где вы вручную обновите идентификаторы разделов с помощью недавно сохраненных идентификаторов документов.
Это можно продемонстрировать на следующем фасаде:
@Stateless
public void DocumentFacade implements DocumentFacadeLocal {
@PersistenceContext
private EntityManager entityManager;
public void save(Document entity) throws Exception {
this.entityManager.persist(entity);
this.entityManager.flush();
this.persistTransientEntities(entity);
this.entityManager.flush();
}
private void persistTransientEntities(CaseInstructionSheet entity) {
for (Section section : entity.getSections()) {
this.entityManager.persist(section);
}
}
}