Solucionado (ver solução)
Solucionado
(ver solução)
11
respostas

Persistir vários Objetos na mesma transação com CDI

Gostaria de saber como posso persistir vários objetos que se relacionam dentro da mesma transação utilizando CDI, por exemplo, ao salvar uma Pessoa, o mesmo deverá salvar o Contato, Documento, Endereço etc..

11 respostas

Oi lvwagner,

Se o projeto estiver utilizando JPA, dá pra fazer essa configuração via cascade . Algo como:

@Entity
public class Pessoa {
    @Id @GeneratedValue(strategy = IDENTITY)
    private Long id

    @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE})
    private Endereco endereco;

    //outros atributos...

Bons estudos!

Olá Rodrigo, obrigado pela resposta, mas esqueci de colocar no tópico que é sem o uso de Cascade, e sem relacionamento Bidirecional. Pessoa não conhece Endereco, e sim Endereco tem a chave de Pessoa a qual ele pertence.

Acho que então você vai precisar persistir todas as informações separadas:

public void save(Pessoa pessoa) {
    this.manager.persist(pessoa);
    this.manager.persist(pessoa.getEndereco());
    //...
}

Então Rodrigo, não sei se fui bem claro, mas por exemplo, como eu disse, Pessoa nao conheçe endereço, então pesso.getEndereco() não é possível fzr, não ainda da forma que esta aqui, apenas Endereco conheçe Pessoa, então eu faço endereco.setPessoa(registro); registro é a instacia que esta sendo criada. Eu utilizo padrão MVC com genérics, então quem vai persistir o Endereco, é o EnderecoDao, quem persist pessoa é a classe que foi estanciada para o tipo de pessoa, exemplo Usuario, então UsuarioDao, pois eu faço polimorfismo com Pessoa, PF e PJ, então a classe UsuarioDao persistira o Usuario do tipo PF ou PJ, conforme a escolha do usuário.

Eu estou fazendo de uma forma com @Transactional, mas eu gostaria de ver se tem outra forma, e como o pessoal utiliza.

Lembrando que ao persistir o tipo de Pessoa, tera que persistir as outras entidades que listei, se uma falhar tem q acontecer o rollback, ou seja tudo na mesma transação

Ah blz!

Nesse caso então acho que poderia adicionar o @Transactional no Controller/ManagedBean que está chamando as Dao's, pois assim as 2 Dao's fariam parte da mesma transação.

Eu prefiro trabalhar apenas com uma classe de Negócio no Controller. Mas você diz isso né?

public class UsuarioController extends AbstractController<Usuario> implements Serializable {

@Override
@Transactional
public void salvar(){
    usuarioBusiness.salvar(registro);
    enderecoBusiness.salvar(endereco);
}

exemplo, se falhar o endereco, vai acontecer rollback de tudo?

Isso mesmo!

Rodrigo, fiz um teste aqui para ver o rollback, e não está acontecendo caso alguma entidade n seja persistida. Por padrão o @Transactional não faz rollback?

O rollback só acontece, por padrão, no caso de ser lançada uma RuntimeException.

Se for checked exceptions o raollback não é feito por padrão, mas dá para configurar na annotation:

@Transactional(rollbackOn = {SuaException.class, OutraException.class})

Entendi, e oque seria melhor , eu utilizar ExceptionHandler?, ou criar uma classe que extends de Exception e então nos métodos salvar() atualizar() do AbstractBusiness e AbstractController eu fzr eles lançar um throws ? por exemplo

@Override
 public void salvar(T registro) throws BusinessExceptions{}

preciso muito definir essa parte Rodrigo, porque pelo que parece terei q lançar exceções para conseguir fzr o rollback, pelo que notei, o @Transaction só fará rollback se alguma exception for lançada pelo banco, me corrija se estou errado, por favor.! Desde já agradeço muito todo help!

solução!

Oi Ivwagner,

Na verdade você nem precisa fazer nada em relação a excpetion, porque na sua classe dao a propria JPA vai lançar uma runtime exception se der algum erro na hora de gravar as informações no BD. Daí o rollback será feito automatico por conta do @Transactional.

Apenas se você tiver que fazer alguma lógica de negócio e fazer o rollback caso alguma regra tenha sido violada, é que você vai precisar lançar uma exception da sua classe Business.

Nesse caso você lança a exception e marca o método com o throws. E dá para utilizar um exception handler para capturar a exception e apresentar uma msg ao usuário.

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software