Pergunta

Existe uma alternativa viável ao Hibernate? De preferência algo que não se baseie no JPA.

Nosso problema é que estamos construindo um sistema RIA complexo (como em, muitos objetos se refere um ao outro). Parece que o Hibernate foi projetado para ser usado principalmente em aplicativos únicos - JSF e similares.

O problema é principalmente o do carregamento preguiçoso. Como pode haver várias solicitações HTTP entre a inicialização e realmente carregar coleções preguiçosas, uma sessão por transação está fora de questão. Uma sessão de longa duração (uma por aplicativo) também não funciona bem, porque uma vez que uma transação atinge um obstáculo e lança uma exceção, toda a sessão é invalidada, portanto os objetos carregados preguiçosos quebram. Depois, há todos os tipos de coisas que simplesmente não funcionam para nós (como dados implícitos que persistem de dados de fora de uma transação inicializada).

Minhas más explicações à parte, o ponto principal é que o Hibernate faz mágica que não gostamos. Parece que Toplink não é melhor, também está sendo escrito no topo do EJB.

Portanto, uma camada de persistência apátrida (ou mesmo camada de abstração de banco de dados orientada a objetos brilhantes) é o que mais precisaríamos.

Algum pensamento, ou estou pedindo algo que não existe?

Editar: Sinto muito pela minha terminologia ambígua e obrigado a todos por suas correções e respostas perspicazes. Aqueles que me corrigiram, todos vocês estão corretos, eu quis dizer JPA, não EJB.

Foi útil?

Solução

Como mencionado, jpa <> ejb, eles nem estão relacionados. O EJB 3 passa a alavancar o JPA, mas é isso. Temos um monte de coisas usando o JPA que nem chega perto de executar o EJB.

Seu problema não é a tecnologia, é o seu design.

Ou, devo dizer, seu design não é fácil de se encaixar em praticamente qualquer estrutura moderna.

Especificamente, você está tentando manter as transações vivas em várias solicitações HTTP.

Naturalmente, quase todo idioma comum é que cada solicitação é em si uma ou mais transações, em vez de cada solicitação ser uma parte de uma transação maior.

Também há confusão óbvia quando você usou o termo "apátrida" e "transação" na mesma discussão, pois as transações são inerentemente com estado.

Seu grande problema é simplesmente gerenciar suas transações manualmente.

Se você está ocorrendo em várias solicitações HTTP, e essas solicitações HTTP estão funcionando "muito rápido", logo após o outro, então você não deve estar realmente tendo nenhum problema real, exceto que você terá para garantir que seu http As solicitações estão usando a mesma conexão de banco de dados para aproveitar as instalações de transação dos bancos de dados.

Ou seja, em termos simples, você obtém uma conexão com o banco de dados, enfia -o na sessão e verifique se, durante a duração da transação, todas as suas solicitações HTTP passam não apenas na mesma sessão, mas também de tal maneira que a conexão real ainda é válida. Especificamente, não acredito que haja uma conexão fora da prateleira JDBC que realmente sobreviva ao failover ou balanceamento de carga de uma máquina para outra.

Portanto, simplesmente, se você deseja usar transações de banco de dados, precisa garantir que você use a mesma conexão de banco de dados.

Agora, se sua transação de longa execução tiver "interações do usuário", ou seja, você inicia a transação do banco de dados e aguarde o usuário "fazer algo", então, simplesmente, esse design está errado. Você não quer fazer isso, pois as transações de vida longa, especialmente em ambientes interativas, são simplesmente ruins. Como "atravessar os riachos" ruim. Não faça isso. As transações em lote são diferentes, mas as transações interativas de longa duração são ruins.

Você deseja manter suas transações interativas como práticas.

Agora, se você não puder garantir que poderá usar a mesma conexão de banco de dados para sua transação, parabéns, você poderá implementar suas próprias transações. Isso significa que você pode projetar seu sistema e fluxos de dados como se não tivesse capacidade transacional no back -end.

Isso significa essencialmente que você precisará criar seu próprio mecanismo para "comprometer" seus dados.

Uma boa maneira de fazer isso seria onde você criará seus dados incrementalmente em um único documento "transação" e, em seguida, alimente esse documento a uma rotina de "salvar" que faz grande parte do trabalho real. Como, você pode armazenar uma linha no banco de dados e sinalizar como "não salva". Você faz isso com todas as suas linhas e, finalmente, chama uma rotina que percorre todos os dados que você acabou de armazenar e marca tudo como "salvo" em um único processo de mini-lote de transações.

Enquanto isso, todos os seus outros SQL "ignoram" dados que não são "salvos". Jogue alguns carimbos de hora e tenha uma eliminação de processos Reaper (se você realmente quiser se preocupar - pode ser realmente mais barato deixar fileiras mortas no banco de dados, depende do volume), essas linhas "não salvas" mortas, pois estes são Transações "não concomitadas".

Não é tão ruim quanto parece. Se você realmente quer um ambiente sem estado, que é o que me parece, precisará fazer algo assim.

Mente, em tudo isso, a tecnologia de persistência realmente não tem nada a ver com isso. O problema é como você usa suas transações, em vez da tecnologia.

Outras dicas

Se você está atrás de outro provedor de JPA (o Hibernate é um deles), dê uma olhada Eclipselink. É muito mais completo do que a implementação de referência do JPA 1.0 do TopLink Essentials. De fato, o Eclipselink será a implementação de referência JPA 2.0 enviada com a Glassfish V3 Final.

O JPA é bom porque você pode usá -lo dentro e fora de um recipiente. Escrevi clientes de swing que usam JPA com bom efeito. Ele não tem o mesmo estigma e bagagem XML que o EJB 2.0/2.1 veio.

Se você está atrás de uma solução de peso ainda mais leve, não procure mais, não ibatis, que considero minha tecnologia de persistência preferida para a plataforma Java. É leve, depende do SQL (é incrível quanto tempo os usuários do ORM gastam tentando fazer com que seu ORM produz um bom SQL) e faz 90-95% do que o JPA faz (incluindo carregamento preguiçoso de entidades relacionadas, se você quiser).

Apenas para corrigir alguns pontos:

  • JPA é a camada de peristência do EJB, não construída no EJB;
  • Qualquer provedor de JPA decente tem muito armazenamento em cache e pode ser difícil descobrir tudo (este seria um bom exemplo de "Por que a simplicidade é tão complexa?"). A menos que você esteja fazendo algo que você não indica, exceções não devem ser um problema para seus objetos gerenciados. Exceções de tempo de execução normalmente transações de reversão (se você usar o gerenciamento de transações da Spring e quem não faz isso?). O provedor manterá cópias em cache de objetos carregados ou persistentes. Isso pode ser problemático se você deseja atualizar fora do gerente de entidade (exigindo uma descarga explícita de cache ou uso de EntityManager.refresh()).

Eu acho que você deveria dar uma olhada Apache Cayenne O que é uma alternativa muito boa às estruturas "grandes". Com seu modelador decente, a curva de aprendizado é reduzida por uma boa documentação.

Eu olhei Simpleorm No ano passado, e ficaram muito impressionados com seu design sem mágica leve. Agora parece haver uma versão 3, mas não tenho nenhuma experiência com essa.

EBean Orm (http://www.avaje.org)

É um ORM mais simples para usar.

  • Usa as anotações JPA para mapeamento (@entity, @onetomany etc)
  • API sem sessão - sem sessão de hibernato ou gerente de entidade JPA
  • O carregamento preguiçoso só funciona
  • Suporte de objeto parcial para maior desempenho
  • Tuning automático de consulta via "Autofetch"
  • Integração da primavera
  • Suporte de consulta grande
  • Ótimo suporte para processamento em lote
  • Busca de fundo
  • Geração DDL
  • Você pode usar SQL bruto se quiser (tão bom quanto ibatis)
  • Licença LGPL

  • Roubar.

Bea Kodo (antigo Kodo Solarmétrico) é outra alternativa. Ele suporta JPA, JDO e EJ3. É altamente configurável e pode suportar a pré-busca agressiva, destacando/anexando objetos, etc.

No entanto, pelo que você descreveu, o Toplink deve ser capaz de lidar com seus problemas. Principalmente, parece que você precisa anexar/destacar objetos da camada de persistência, à medida que as solicitações começam e terminam.

Apenas para referência, por que o design do OP é seu maior problema: abranger transações em várias solicitações de usuário significa que você pode ter tantas transações abertas em um determinado momento quanto há usuários conectados ao seu aplicativo - uma transação mantém a conexão ocupada até que seja comprometida /revertido para trás. Com milhares de usuários conectados simultaneamente, isso pode significar potencialmente milhares de conexões. A maioria dos bancos de dados não suporta isso.

Nem o hibernato nem o toplink (Eclipselink) são baseados no EJB, ambos são estruturas de persistência de pojo (ORM).

Concordo com a resposta anterior: o ibatis é uma boa alternativa às estruturas ORM: controle total sobre o SQL, com um bom mecanismo de armazenamento em cache.

Uma outra opção é o torque, não estou dizendo que é melhor do que qualquer uma das opções mencionadas acima, mas apenas que é outra opção para olhar. Está ficando bastante velho agora, mas pode atender a alguns dos seus requisitos.

Torque

Quando eu mesmo, procurei um substituto para hibernar, tropecei Plataforma de acesso a DataNucleus, que é um ORM licenciado por Apache2. Não é apenas o ORM, pois fornece persistência e recuperação de dados também em outras fontes de dados que o RDBMS, como LDAP, DB4O e XML. Não tenho nenhuma experiência de uso, mas parece interessante.

Considere quebrar seu paradigma completamente com algo como tox. Se você precisar de aulas de Java, pode carregar o resultado XML em JDOM.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top