estou desenvolvendo um sistema com swing e JPA.
tenho minhas classes geradas a partir das tabelas do BD e o programa funciona assim:
Clico em um botão da janela e um conteúdo do Banco de dados é mostrado no centro dela em uma JTable .
O problema ocorre quando eu modifico um dado no BD (um nome de um funcionário, por exemplo) e mesmo quando limpo todos os componentes da janela e clico para exibir os dados novamente, eles continuam os mesmos. Parece que os objetos JPA não são atualizados.
E no meu código sempre que o botão é cllicado é criada uma nova instancia, mas não está atualizando os dados do BD.
Usar JPA/Hibernate é uma grande aventura. Depende de como está implementado. Certifique se está abrindo uma nova session a cada ação do usuário, senão ele vai pegar do cache mesmo.
OLÁ,
sou novo nessa aventura e o que vc quer dizer com “abrindo uma nova session”?
vc se refere a fechar e abrir um novo EntityManagerFactory a cada acao?
Na época que usava Java tinha o SessionFactory (instancia que deve ser única, alocado na aplicação a vida toda). Com ele chamava o método openSession para abrir a conexão com o banco. Seja lá qual for o “comando” ou mágica hoje, cada vez que o usuário realizar uma ação no sistema, a conexão com o banco de dados deverá ser aberta e fechada assim que terminar de retornar os dados pro usuário. Dependendo de como estiver implementado, se manter a session (não SessionFactory) aberta a vida toda corre o risco dele ler do cache ao invés do banco de dados.
Isso funciona, mas evict é pra ser usado em último caso em situações anormais. Provavelmente está usando cache sem necessidade, deixando a conexão sempre aberta, ou algo que vá ficar encoberto e sendo remediado por evicts.
Curioso que cache quando realmente necessário é um dos poucos motivos para se usar JPA/Hibernate, a não ser que esteja usando vários SGDBs ao mesmo tempo.
A atualização que eu me refiro, Deivid, é uma consulta (um select usando JPA). O problema é que essa consulta mostra sempre os mesmos dados, ainda que eu modifique os dados no BD usando o phpmyadmin, por exemplo. Aí quando clico pra listar os dados novamente ele não muda.
vou verificar e aplicar o código que vcs me passaram e informo o resultado sem usar evict.
Se você fizer como o exemplo que ele passou, sendo que para consulta, continua o problema?
Session sessao = sessionFactory.openSession();
Query query = sessao.createQuery("from Cliente where id = :id ");
query.setParameter("id", "123");
List resultado = query.list();
//....passa o resultado pra um DTO, ModelView ou que for que esteja usando pra servir de interface pra atender a UI.......
sessao.close();
Olá gente, agradeço muito a ajuda de vcs. Encontrei o meu erro!
Como eu estou entrando agora nessa onda de JPA desconhecia que sempre temos que criar uma nova EntityManagerFactory a cada interação com o BD e sempre fechá-la. Eu usava um EntityManagerFactory único em uma variável static por achar que cada abertura deixaria o programa pesado, mas não.
Eis aki o meu código SEM ERROS.
public class PainelListaDeFuncionarios extends javax.swing.JPanel implements ActionListener{
private final DefaultTableModel modelo1;
private final JanelaPrincipal janelaPai;
fctr = Persistence.createEntityManagerFactory("com.sigef_jar_1.0-SNAPSHOTPU");
FuncionarioJpaController fJpaC =
new FuncionarioJpaController(fctr);
funcionarios = fJpaC.findFuncionarioEntities();
int numRow = modelo1.getRowCount();
Object[] line;
Funcionario funcion;
for (int idx = 0; idx < funcionarios.size(); idx++) {
funcion = funcionarios.get(idx);
line = new Object[]{
funcion.getPessoa().getPessoaPK().getId(),
funcion.getPessoa().getNome(),
funcion.getCargo().getNome(),
funcion.getPessoa().getNascimentoData()
};
modelo1.addRow(line);
}
//IMPORTANTE PARA FECHAR AS CONEXÕES DO BD
fctr.close();
}
}
temos que sempre abrir com o createEntityManagerFactory() e fechar. Erro grosseiro! Mas valeu a experiência. Obrigado gente!
agora meu software vai ficar perfeito.
Pois é, mas já que insistem em usar JPA/Hibernate sem sem ter a necessidade dessa coisa toda de cache, então ele vai ter que reabrir a conexão a cada consulta ou usar StatelessSession. Ele está usando uma ferramenta que está atrapalhando mais do que ajudando, ou se ao menos tivesse justificado o uso, como por exemplo multibanco.
When the application has finished using the entity manager factory, and/or at application shutdown, the application should close the entity manager factory. Once an EntityManagerFactory has been closed, all its entity managers are considered to be in the closed state.
não fechei o EntityManagerFactory e funcionou da mesma forma! Agora tenho que criar apenas um EntityManagerFactory e usá-lo sempre em todas as classes e fechar apenas quando a aplicação for fechada?
Achei que tivesse fechado só a session como o exemplo que passamos. O factory não é para fechar não! Factory é super pesado deve existir uma única instância em todo a vida da aplicação como já explicado no início.