JPA atualização dentro de uma transação

Galera,

Estava lendo o livro de EJB 3 e na parte de JPA surgiu algumas dúvidas.
Vou postar alguns exemplos, o código está cheio de “marreta”, pois é só pra teste, para que eu não precise mostrar códigos de outras camadas.
Os trechos de código abaixo são executados dentro de métodos EJB gerenciados pelo container, todos eles com transação REQUIRED.

1 - O método flush força o banco de dados a ser atualizado conforme dados da entidade gerenciada.

Cliente clienteAlterar = entityManager.find(Cliente.class, cliente.getId());
clienteAlterar.setAltura(185);
entityManager.merge(clienteAlterar);
entityManager.flush();
System.out.println(); // breakpoint aqui.

1.1 - Depois de executar o método flush, o mesmo deveria ser forçado a persistir no banco?
Porque nesse caso a transação ainda
não terminou.

Fazendo os testes ao chegar no breakpoint fui na base e conferi os dados e a altura do cliente ainda não havia sido
atualizada, isso ocorreu só depois do término do método, uma vez que a transação foi finalizada.
1.2 - Então o flush nesse cenário não serviu de nada?

2 - O método refresh força a entidade gerenciada a ser atualizada com os dados do banco.

Cliente clienteAlterar = entityManager.find(Cliente.class, 1);
System.out.println(); // breakpoint aqui.
entityManager.refresh(clienteAlterar);

O que fiz para testar:
Quando o código parou no breakpoint, fui na base alterei uma informação do registro de código 1 (referente ao que acabei de pesquisar).
Ao chamar o método refresh esperava que a minha entidade estivesse atualizada, porém isso não aconteceu, o console até mostra
a instrução select, porém não refletiu na entidade gerenciada.

Alguém sabe porque?

vlw galera.

  1. Você viu no log se ele disparou o insert?
  2. EJB trabalha com cache das entidades.

Hebert,
Sim, ele dispara a instrução antes do método finalizar, mas a alteração só é concluída no banco ao término do método.

Apesar que mesmo não chamando o flush ele também dispara a instrução.

Se não me engano isso pode estar relacionado ao tipo de configuração no entity manager.

Se você não leu isso, vai ler ainda. Tem como definir se ele realizará ou não o insert no db.

O que você poderia fazer é apenas na hora do persist, chame um método anotado com @RequiresNew.

Com REQUIRES_NEW ele vai trabalhar na transação separada, independente das outras ele será persistido.

Em relação a configuração do entinty.
Poderiam ser 2.

  • O modo de flush:

AUTO ou COMMIT.

AUTO como default já não atende.
COMMIT também não vai atender porquê estamos deixando o tratamento para o container.

  • o tipo de contexto de persistência.
    PersistenceContextType.EXTENDED ou PersistenceContextType.TRANSACTION

Mas acho que nenhum deles vai resolver.

O contexto PersistenceContextType.TRANSACTION é o default, não atende.

PersistenceContextType.EXTENDED só libera a operação quando fecha o entityManager.

Eu acho hehehehehhehe

Isso que estou postando é só exemplo mesmo, curiosidades de quem está lendo o livro.
O livro cita a importância do refresh logo depois do persist ou merge no seguinte cenário:

Você não passa o atributo “dataAtual” por exemplo, o banco está configurado para colocar a data atual, sendo assim, quando fizer o persist a
entidade vai voltar com o valor null, porquê você não enviou a data, mas se fizer o refresh agora já estaria com a data no atributo (é o que não está acontecendo )