5
respostas

Persistindo Objeto contendo mais objetos como atributos ?

Olá,

Se por exemplo na classe Produto eu teria como atributo o fabricante que fosse do tipo Fabricante. No momento de chamar o cadastrar ele me traria um Objeto Produto que conteria um Fornecedor (sabendo que nenhum dos dois ainda não está no banco de dados). Fiz um teste e foi gerada a seguinte exception: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing

Ou seja, meu objeto Fornecedor não está no banco.

Neste caso tenho que injetar mais um daoFornecedor no meu ProdutoController, persistir o Fornecedor e depois o Produto ?

5 respostas

Olá Leandro!

Estou fazendo o curso Java e JPA agora mesmo e acabei de ver um exemplo semelhante ao que você precisa.

Neste caso, você precisa primeiro persistir os seus "objetos interiores" se eles ainda não existem no banco. E depois disso você persiste o principal.

entityManager.persist(fabricante);
entityManager.persist(produto);

Como informado no erro, o seu objeto Fabricante está como Transient, ou seja, ele ainda não está como objeto gerenciado pelo JPA. Assim que você realizar o persist nele, ele passa a ser gerenciado (managed), então ao persistir o produto ele entende que o Fabricante existe.

P.S. Esta é a característica do JPA, porém não sei se no framework Spring há uma funcionalidade que já persiste tudo facilmente.

Obrigado Giovane!

Sim, também vi esta solução no curso de JPA. Aparentemente resolvi este problema persistindo o Fabricante antes do Produto.

Agora minha duvida é: o ProdutoDao que deve persistir o Fabricante e depois o Produto ? ou devo fazer um FabricanteDao e chamar o fabricanteDao no ProdutoController e dar um fabricanteDao.gravar e logo apos produtoDao.gravar() ?

Bom, você pode fazer isso, mas não acho que deve.

Se você faz o ProdutoDAO chamar o FabricanteDAO você viola o Single Responsibility Principle (SOLID).

Acredito que nesses casos você deve ter uma classe ProdutoFactory, vai depender do tipo de Design Pattern você está trabalhando, e nela você chama os dois DAOs (Fabricante e Produto) na ordem correta fazendo a criação do produto.

Ai seu Controller só fala assim:

factory.add(produto);

E sua factory se encarrega de fazer o trabalho :)

O que fiz agora pra resolver o problema foi chamar o manager.persist(forncedor) e depois manager.persist(produto) no metodo gravar() de ProdutoDao.

Será que é uma forma elegante de resolver isso ?

Somente para deixar o tópico completo e consequentemente ajudar outros que terão a mesma duvida.

Acredito ter resolvido o problema de uma forma elegante.

O JPA possui uma anotação chamada cascade.

Basta você anotar os atributos de sua classe utilizando cascade = CascadeType.PERSIST, assim chamando o metodo persist(produto) ele também irá persistir forncedor.

Espero ter ajudado.