EJB3 e persistência de hierarquia manual

Eu tenho um database legado, que estou usando o EJB3 para modelar. O database está em péssimo estado, e temos certas restrições incomuns sobre como inserimos no database. Agora eu quero modelar o database em uma hierarquia que se encheckbox com a estrutura do database, mas eu quero ser capaz de inserir manualmente cada entidade individualmente sem o persistence manager tentando persistir as entidades children.

Eu estou tentando algo como o seguinte (boilerplate deixado de fora):

@Entity @Table(name = "PARENT_TABLE") public class Parent { @Id @Column(name = "ID") int id; @OneToMany List children; } @Entity @Table(name = "CHILD_TABLE") public class Child { @Id @Column(name = "ID") int id; } 

Agora isso lança uma exceção:

 java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST 

Agora eu sei que a entidade não está marcada PERSIST – Eu não quero que o EntityManager persista! Eu quero ser capaz de persistir o pai primeiro e depois a criança – mas não juntos. Há boas razões para querer fazer assim, mas não parece querer jogar.

Heh bem-vindo ao hair-pulling que é a configuração JPA.

No seu caso, você tem duas opções:

  1. Manter manualmente o novo object; ou
  2. Automaticamente persistir.

Para persistir automaticamente, você precisa anotar o relacionamento. Este é um idioma comum de um para muitos:

 @Entity @Table(name = "PARENT_TABLE") public class Parent { @Id private Long id; @OneToMany(mappedBy = "parent", cascade = CascadeType.PERSIST) private Collection children; public void addChild(Child child) { if (children == null) { children = new ArrayList(); } child.setParent(parent); children.add(child); } } @Entity @Table(name = "CHILD_TABLE") public class Child { @Id private Long id; @ManyToOne private Parent parent; public void setParent(Parnet parent) { this.parent = parent; } } Parent parent = // build or load parent Child child = // build child parent.addChild(child); 

Por causa da cascata persistir isso vai funcionar.

Nota: Você precisa gerenciar o relacionamento em um nível Java, definindo manualmente o pai. Isso é importante.

Sem isso, você precisa persistir manualmente o object. Você precisará de um EntityManager para fazer isso, nesse caso, é tão simples quanto:

 entityManager.persist(child); 

Nesse ponto, ele funcionará corretamente (assumindo que todo o resto funciona).

Para entidades puramente filhos eu favoreceria a abordagem de anotação. É apenas mais fácil.

Há uma pegadinha que mencionarei com a JPA:

 Parent parent = new Parent(); entityManager.persist(parent); Child child = new Child(); parent.addChild(child); 

Agora estou um pouco enferrujado, mas acredito que você possa ter problemas se fizer isso porque o pai persistiu antes que a criança fosse adicionada. Tenha cuidado e verifique este caso, não importa o que você faça.