Java, lidando com classes anotadas XML e JPA

Sep 14 2020

Eu uso o xjc para compilar arquivos XSD para classes Java e quero editá-los / estendê-los para torná-los persistentes por meio de JPA.

Não consigo descobrir qual é o melhor "Acoplamento?" seria e como organizá-lo, se eu modificar as classes compiladas xjc para serem persistentes, eu perderia a capacidade de recompilar o XSD se houver alguma alteração.

Mesmo se eu não precisasse recompilar, em alguns casos, eu ainda não seria capaz de serializar / desserializar os Dados que foram coletados antes da mudança do meu Schema.

Não quero "desacoplar" completamente, pois quero manter a capacidade de Persistir o Objeto XML importado com apenas algumas linhas de código (não ter que escrever uma espécie de "conversor" para cada Entidade XML).

Alguém já enfrentou o mesmo problema? Como você conseguiu resolver isso.

Respostas

JohannesHahn Sep 14 2020 at 22:08

Acho que o maior problema que você está enfrentando aqui é que, para classes que precisam ser "visíveis" para algo fora do seu código, é importante ter uma fonte de verdade para o que conta como dados válidos. Caso contrário, você acabará com infinitas horas de trabalho gastas em sincronizar as muitas definições e suas implementações. As especificações estão fora de sincronia (ou ficam fora de sincronia com o tempo) ou os conversores são incompatíveis com as versões mais recentes das especificações etc. No seu caso, as classes são visíveis para

  • o que quer que esteja produzindo / consumindo os dados XML que são convertidos de / para as classes Java
  • e para o banco de dados por trás do JPA, que impõe seus próprios requisitos de tipo e integridade de dados aos seus dados.

Sua abordagem corre o risco de violar este princípio importante se você não tomar cuidado com isso. Ou o XSD é a fonte da verdade ou as definições JPA são ou algo totalmente diferente é, mas de acordo com este princípio n-1 de n definições têm que ser dependentes do enésimo.

Então qual é a solução? Como sempre, depende fortemente do que você deseja fazer.

  1. Talvez não existam muitas classes e talvez elas nunca mudem ou mudem apenas muito pouco e muito raramente. Nesse caso, você pode decidir aceitar o custo de ter duas fontes da verdade.

    Como você faria isso? Como você já disse, é muito frágil modificar código gerado automaticamente. Também é um trabalho desnecessário ter (sub) classes separadas apenas para as anotações JPA, porque isso exigiria muitos códigos clichê para os conversores. Felizmente, a especificação JPA permite a configuração XML dos mapeamentos ORM em vez da configuração usual baseada em anotação. Dê uma olhada no arquivo orm.xml . Com ele, você pode definir uma classe para ser uma entidade JPA sem nenhuma modificação em seu código-fonte.

  2. Se o seu XSD for simples o suficiente, pode ser possível gerar a estrutura do banco de dados diretamente do XSD. Existem ferramentas para isso. Isso não dá a você o mapeamento ORM. Mas se o XSD for simples o suficiente, também pode ser possível gerar automaticamente o arquivo orm.xml a partir do XSD. Isso restabeleceria o XSD como sua única fonte de verdade.

  3. Se 1. e 2. não são opções para você, porque sua estrutura de dados é muito complicada, talvez seja possível ter uma terceira especificação que pode servir como a fonte da verdade para ambos e é capaz de gerar os XSDs e os Definições JPA de alguma forma. Em princípio, você poderia ter um arquivo XML aumentado que contenha as definições XSD e ORM, bem como um XSLT que extraia as duas metades. (É claro que você pode usar qualquer outra (meta-) linguagem em vez de XML para a especificação mestre, se desejar) Então, seu processo de compilação precisaria de outra etapa à frente. Mas cuidado: dependendo das complicações em sua estrutura de dados, pode ser extremamente difícil depurar / modificar, se necessário.

  4. Você poderia ter o código Java como a fonte da verdade e exportar o XSD. Claro, então você poderia usar a exportação JSON em vez de XML com muito mais facilidade. Não acho que seja muito provável, porque os XSDs geralmente são fornecidos a partir de especificações externas e não gerados por capricho, mas hey, talvez você seja a exceção à regra?

Em qualquer caso, você precisa estar ciente de que os pontos mais delicados de XMLs e ORMs como JPA não são necessariamente compatíveis uns com os outros e seu desejo de uma unificação completa pode estar condenado desde o início. Pode ser simplesmente que alguns aspectos de seus dados XML não possam ser convertidos em banco de dados e vice-versa. Por exemplo: Um conceito de transações não existe na terra do XML. A JPA tem conhecimento (limitado) de procedimentos armazenados, acionadores de banco de dados e outros recursos (semi) avançados de bancos de dados. Não estou ciente de nada no terreno do XML que seja semelhante a isso. E, por outro lado, não existe um primo próximo do XSLT no terreno do banco de dados.

Além disso: o JPA pode ser muito ineficiente se você estiver lidando com grandes quantidades de dados; ele às vezes grava um SQL horrendo se sua configuração não estiver otimizada; tem algum comportamento não completamente direto com transações, carregamento lento etc. É ótimo para abstrair os detalhes de bancos de dados, mas como qualquer abstração pode custar se você não souber o que está fazendo. Pode ser simplesmente impossível obter todos os pontos mais precisos corretos quando você deixa tudo isso para uma ferramenta automatizada.

Você deve ter isso em mente para que possa fornecer boas interfaces tanto para adicionar recursos ausentes em ambas as extremidades quanto para ajustar os mapeamentos.