JPA+Hibernate - alteração diretamente no nanco não refletem no JPA

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?

Posta o codigo da gravacao. Pode estar faltando Flush ou Commit.

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.

Pode ser isso mesmo, devido a amaldiçoada Session com cache.

Para consultas prefira usar Stateless Session.

[quote=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?[/quote]

Onde você leu que JPA reconhece as mudanças feitas por fora do sistema?

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.

[quote=pfk66][quote=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?[/quote]

Onde você leu que JPA reconhece as mudanças feitas por fora do sistema?[/quote]
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.

[quote=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.[/quote]

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.

[quote=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.[/quote]

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.

javaflex, qual a vantagem de usar ferramentas ORM no seu caso, se você prefere o acesso direto, desabilitando os recursos que a ferramenta oferece?

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.

[quote=pfk66][quote=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.[/quote]

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.

[quote=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.[/quote]

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.[/quote]
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.

[quote=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.[/quote]

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:

https://msdn.microsoft.com/en-us/magazine/hh205755.aspx

[quote=pfk66][quote=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.[/quote]

Parece que é isso o problema mesmo, ficar reaproveitando o session.
[/quote]
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.

[quote=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.[/quote]

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.

[quote=pfk66][quote=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.[/quote]

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.[/quote]
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.

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();
}


a explicação está nesse link:

Sei que é meio antigo esse post, fiz um tutorial sobre JPA, com a sua configuração, por favor, veja se ajuda.
Seguem os links:
http://www.tidicas.com.br/?p=130
http://www.tidicas.com.br/?p=1864