JPA+Hibernate - alteração diretamente no nanco não refletem no JPA
16 respostas
E
ensinati
Olá pessoa, tenho uma aplicação que utiliza JPA para mapear algumas tabelas de uma sistema legado. O problema é que quando o sistema legado altera as tabelas o JPA não reconhece as mudanças.
Já procurei bastante e não encontrei nada que funcione.
Posta o codigo da gravacao. Pode estar faltando Flush ou Commit.
R
rodrigo.uchoa
Não sei se é esse o caso, mas só lembre que o JPA não detecta mudanças no banco automaticamente. Se você tem entidades persistentes já em memória e alguém altera o valor delas diretamente no banco, realmente elas não vão mudar. Você vai ter que dar um “refresh” consultando no banco novamente.
J
javaflex
Pode ser isso mesmo, devido a amaldiçoada Session com cache.
Para consultas prefira usar Stateless Session.
P
pfk66
ensinati:
Olá pessoa, tenho uma aplicação que utiliza JPA para mapear algumas tabelas de uma sistema legado. O problema é que quando o sistema legado altera as tabelas o JPA não reconhece as mudanças.
Já procurei bastante e não encontrei nada que funcione.
Existe alguma forma de resolver esse problema?
Onde você leu que JPA reconhece as mudanças feitas por fora do sistema?
P
pfk66
Geralmente você não deve alterar os dados de uma aplicação ORM diretamente no banco porque pode colocar a aplicação num estado inconsistente.
J
javaflex
pfk66:
ensinati:
Olá pessoa, tenho uma aplicação que utiliza JPA para mapear algumas tabelas de uma sistema legado. O problema é que quando o sistema legado altera as tabelas o JPA não reconhece as mudanças.
Já procurei bastante e não encontrei nada que funcione.
Existe alguma forma de resolver esse problema?
Onde você leu que JPA reconhece as mudanças feitas por fora do sistema?
Ele deve estar deixando a sessão aberta a vida toda. Se ele abrir e fechar a sessão a cada requisição, que é o mais comum, não vai ter esse problema.
A outra opção é ele usar StatelessSession para se libertar do cache e poder fazer querys sempre pegando do banco, de quebra acabando com a bagunça dos lazys e múltiplas querys, dando fetch conforme demanda da solicitação do usuário. No meu caso para consultas uso SQL mesmo, mais natural da fonte que uso, não quebrando a cabeça pra ser extremo OOP.
P
pfk66
javaflex:
Ele deve estar deixando a sessão aberta a vida toda. Se ele abrir e fechar a sessão a cada requisição, que é o mais comum, não vai ter esse problema.
abrir e fechar a sessão na hora que usar não vai proteger sua aplicação de dados inconsistentes serem introduzidos por fora da aplicação.
javaflex:
A outra opção é ele usar StatelessSession para se libertar do cache e poder fazer querys sempre pegando do banco, de quebra acabando com a bagunça dos lazys e múltiplas querys, dando fetch conforme demanda da solicitação do usuário. No meu caso para consultas uso SQL mesmo, mais natural da fonte que uso, não quebrando a cabeça pra ser extremo OOP.
Não estou falando de ser OOP extremo, mas de software que funciona. Se os dados dos objetos no banco podem mudar sem conhecimento da aplicação, ninguém tem como garantir nada sobre a consistência dos dados que aplicação precisa pra funcionar e isso significa que ela pode deixar de funcionar a qualquer momento.
P
pfk66
javaflex, qual a vantagem de usar ferramentas ORM no seu caso, se você prefere o acesso direto, desabilitando os recursos que a ferramenta oferece?
J
javaflex
Não preciso usar todos os recursos que a ferramenta oferece para todos os casos. Me referi a consultas e relatórios, casos não simples lógico.
Então uso o que for melhor para cada caso, não sendo a toa que o próprio hibernate nos dá abertura a SQL nativo e session magra sem estado gerenciado, para casos que seja desperdício de recursos usar. Para persistência e leitura pontual, uso o “normal”, que realmente me ajuda mais, claro que utilizando uma session para cada requisição para não dar esses rolos da questão do tópico.
J
javaflex
pfk66:
javaflex:
Ele deve estar deixando a sessão aberta a vida toda. Se ele abrir e fechar a sessão a cada requisição, que é o mais comum, não vai ter esse problema.
abrir e fechar a sessão na hora que usar não vai proteger sua aplicação de dados inconsistentes serem introduzidos por fora da aplicação.
javaflex:
A outra opção é ele usar StatelessSession para se libertar do cache e poder fazer querys sempre pegando do banco, de quebra acabando com a bagunça dos lazys e múltiplas querys, dando fetch conforme demanda da solicitação do usuário. No meu caso para consultas uso SQL mesmo, mais natural da fonte que uso, não quebrando a cabeça pra ser extremo OOP.
Não estou falando de ser OOP extremo, mas de software que funciona. Se os dados dos objetos no banco podem mudar sem conhecimento da aplicação, ninguém tem como garantir nada sobre a consistência dos dados que aplicação precisa pra funcionar e isso significa que ela pode deixar de funcionar a qualquer momento.
Não me referi a isso. Isso ai acontece em qualquer sistema multiusuário em concorrência otimista. Lógico quando tiver um caso crítico em que exija tratamento pessimista, isto deve ser considerado. O que não pode acontecer nesses casos é deixar uma session com cache do Hibernate aberta o tempo todo para todas as requisições do usuário, assim sempre vai enxergar a atualização da session.
P
pfk66
javaflex:
Não me referi a isso. Isso ai acontece em qualquer sistema multiusuário em concorrência otimista. Lógico quando tiver um caso crítico em que exija tratamento pessimista, isto deve ser considerado. O que não pode acontecer nesses casos é deixar uma session com cache do Hibernate aberta o tempo todo para todas as requisições do usuário, assim sempre vai enxergar a atualização da session.
Parece que é isso o problema mesmo, ficar reaproveitando o session.
Mas eu estava falando da consistência do modelo de objetos, e não dos dados, e permitir que sejam alterados por fora pode ser incompatível com DDD:
Não me referi a isso. Isso ai acontece em qualquer sistema multiusuário em concorrência otimista. Lógico quando tiver um caso crítico em que exija tratamento pessimista, isto deve ser considerado. O que não pode acontecer nesses casos é deixar uma session com cache do Hibernate aberta o tempo todo para todas as requisições do usuário, assim sempre vai enxergar a atualização da session.
Parece que é isso o problema mesmo, ficar reaproveitando o session.
Pois é, o mais provável. Mais complicado mesmo é o autor do tópico não dá retorno.
Ok. Sobre a questão do DDD, não costumo levar em consideração recomendações técnicas adicionais, sem antes ter um problema real que me mova a procurar a solução técnica adicional.
P
pfk66
javaflex:
Ok. Sobre a questão do DDD, não costumo levar em consideração recomendações técnicas adicionais, sem antes ter um problema real que me mova a procurar a solução técnica adicional.
Eu concordo que não existe incentivo para programadores se preocuparem com o problema de alguém alterar os dados no banco, e colocar o sistema num estado inválido, porque geralmente isso acontece com o sistema em produção, quando os técnicos já foram embora, e não durante a fase de desenvolvimento.
J
javaflex
pfk66:
javaflex:
Ok. Sobre a questão do DDD, não costumo levar em consideração recomendações técnicas adicionais, sem antes ter um problema real que me mova a procurar a solução técnica adicional.
Eu concordo que não existe incentivo para programadores se preocuparem com o problema de alguém alterar os dados no banco, e colocar o sistema num estado inválido, porque geralmente isso acontece com o sistema em produção, quando os técnicos já foram embora, e não durante a fase de desenvolvimento.
Se a equipe precisa de DDD para não cometer problemas graves em produção ou o banco de dados tem problemas de segurança, pode ser opção sim usar, vai de cada time escolher o que precisa ou não.
A
aprendizweb
Sei que o topico é antigo, porém é bom postar uma solução caso alguém se encontre com o mesmo problema.
no seu entityManager adicione a opção abaixo, depois um F5 na aplicação e pronto! getEntityManagerFactory().getCache().evictAll();
exemplo:
private static final EntityManagerFactory emf = Persistence.createEntityManagerFactory("teste");
public static EntityManager getEntityManager() {
emf.getCache().evictAll();
return emf.createEntity();
}