JPA 2: Hibernate ou EclipseLink?

Qual implementação de JPA você utiliza? Bom, durante muito tempo achei que a resposta automática para esta pergunta seria Hibernate, porém este ano fiz uma migração de um sistema grande que estávamos usando Hibernate para o EclipseLink. A escolha para o Hibernate era clara, experiência da equipe, aplicação rodando em WildFly, a princípio, melhor desempenho e por aí vai. Agora, por que trocamos de implementação? Vou responder esta pergunta com uma série de posts. Neste vou abordar sobre curiosidades nas diferenças das duas implementações. Os testes foram feitos usando Ubuntu, MySql, EclipseLink 2.6 e Hibernate 4.3.8 em um ambiente JavaSE. Mas não deixe de conhecer outras como OpenJPA e Batoo, sendo que esta última possui benchmarks até melhores que o Hibernate.

O primeiro item que muitos alunos me perguntam é relacionado à perfomance. Bom, quanto a isso não vou me aprofundar muito pois já existem inúmeros trabalhos, maioria até mesmo acadêmicos, como TCC´s. Existe até mesmo artigo comparado JPA com o finado JDO. Em suma, o hibernate costuma ter um desempenho melhor, mas com certeza vale a pena dar uma lida nesta coleção .

Para mostrar algumas curiosidades, vamos usar a relação entre Conta e Movimentação. O pseudo-código abaixo representa a relação.

@Entity
class Conta{

 @Id
 @GeneratedValue(strategy = GenerationType.IDENTITY)
 private Integer id;
 @OneToMany (mappedBy="conta")
 private List<Movimentacao> movimentacoes;
}
@Entity
class Movimentacao{

 @Id
 @GeneratedValue(strategy = GenerationType.IDENTITY)
 private Integer id;
 @ManyToOne
 private Conta conta;
}

Vamos lá.

– Como habilitar os Logs?

Esta é uma propriedade que ainda não foi especificada, logo cada implementação tem a sua.

Hibernate:

<property name=”hibernate.show_sql” value=”true”></property>
<property name=”hibernate.format_sql” value=”true”></property>

EclipseLink:
<property name=”eclipselink.logging.level.sql” value=”FINE” />
<property name=”eclipselink.logging.parameters” value=”true” />

– Devo declarar <class> no persistence.xml?

Bom, aqui já tem diferença. O Hibernate deixa que o mapeamento seja feito apenas através do @Entity, porém o EclipseLink exige que a classes também sejam mapeadas via <class> no persistence.xml.

 

 

– Como gerar a base a partir do modelo?

No JPA 2.1 já houve uma padronização deste parâmetro, agora basta usar a propriedade javax.persistence.schema-generation.database.action. Ela possui 4 valores: create, drop-create, none, drop.

E além disso, foi especificado também a propriedade javax.persistence.schema-generation.scripts.create-target, que permite gerar os arquivos de DDL.Agora

As duas implementações oferecem suporte, entretanto possuem comportamentos diferentes.

EclipseLink: com o banco de dados vazio, ao usar a opção create e rodar o programa, o resultado é a criação da base de dados. Ao inserir uma nova @Entity e rodar novamente o programa, a implementação atualiza a base.

Hibernate: Nestas mesmas condições, ele cria a base na primeira execução, mas na segunda execução ele falha pois tenta criar novamente as mesmas tabelas e falha pois já estão criadas.

A especificação não deixa claro qual deveria ser o comportamento.

Aqui também é importante ressaltar uma outra diferença que impacta diretamente na portabilidade. O EclipseLink gera as tabelas com letras maiúsculas e o Hibernate seguindo o padrão de nome da Classe.

Um outro ponto a ressaltar é que a DDL do EclipseLink é muito mais amigável que a do Hibernate.

EclipseLink:
CREATE TABLE MOVIMENTACAO (ID INTEGER AUTO_INCREMENT NOT NULL, VALOR DOUBLE, CONTA_ID INTEGER, PRIMARY KEY (ID))
ALTER TABLE MOVIMENTACAO ADD CONSTRAINT FK_MOVIMENTACAO_CONTA_ID FOREIGN KEY (CONTA_ID) REFERENCES CONTA (ID)

Hibernate:
create table MOVIMENTACAO (id integer not null auto_increment, valor double precision not null, conta_id integer, primary key (id))
alter table MOVIMENTACAO add constraint FK_pf1tg6j429i17rjrp0pmbw6a3 foreign key (conta_id) references CONTA (id)

 

Bom, esta foi a primeira parte, na segunda parte vou discutir sobre diferenças ao persistir objetos, pesquisas, relacionamentos LAZY e como lidar com o weaving. Aqui na Caelum já falamos muito sobre JPALazy Loading, trabalhos Batch, boas práticas e muitos outros artigos, não deixe de ler, assim como acompanhar apresentações que sempre acontecem sobre a tecnologia e o excelente livro do Hebert (desenvolvedor da DSL Easy Criteria) publicado pela casa do código. Não deixe de comentar e até o próximo post.

 

ps: Bom, hoje é uma data especial pra mim, por isso aproveito o espaço para lançar um desafio aos companheiros da Caelum e quem tiver afim de embarcar nesta. #façaUmPostNoSeuAniversário

 

 

26 Comentários

  1. Lucas Moreira 28/04/2015 at 11:12 #

    Massa, Rapha! Parabéns pelo post… muito bom! E, parabéns pelo aniversário!

  2. Fernando 28/04/2015 at 12:30 #

    Muito legal o post, e parabéns man pelo aniversario

  3. Kalil Peixoto 28/04/2015 at 13:22 #

    Realmente, muito bom o post Raphael, já usei as duas implementações e no que tange ao que foi necessário até então de requisito não-funcional, não vi muita diferença, só mesmo da obrigatoriedade do mapeamento das entities em xml para um e para o outro não.

    Parabéns!!

  4. Luis Amaral 28/04/2015 at 13:39 #

    Muito interessante o seu post, Raphael! Parabéns!
    Estou aguardando os próximos posts…

    Abraços

  5. Rasa 28/04/2015 at 17:24 #

    Raphael, Parabéns!

    Você vai falar de multi-tenancy nos próximos posts? É um assunto interessante e talvez tenham algumas diferenças legais entre Hibernate e EclipseLink.

  6. Ranlive Hrysyk 28/04/2015 at 17:51 #

    Uma outra diferença que notei nos meus projetos foi utilizando primary key autogerada a partir de uma tabela. Com o Hibernate ele cria o registro e o atualiza, já com o EclopseLink era preciso criar o registro manualmente, pois ele somente atualizava.

    Parabéns pelo aniversário.

  7. Adão NUnes 28/04/2015 at 18:29 #

    Raphael parabéns pelo seu aniversário e pelo post…muito interessante!
    Ficarei a esperar dos próximos posts.

  8. Gilmar 29/04/2015 at 08:44 #

    Raphael Lacerda, primeiro FELIZ PARABÉNS 🙂

    Saúde e Sucesso pra ti…
    Segundo, vou acompanhar este tema de perto, quero conhecer um pouco mais do EclipseLink. E vou tentar sim #façaUmPostNoSeuAniversário

    Abraços!

  9. Bruno Bastos 29/04/2015 at 10:43 #

    Muito bom o post Raphael! E parabéns pelo aniversario!
    Só uma duvida, na geração das tabelas o Hibernate botou “precision not null” no valor enquanto o EclipseLink não. Esse atributo não está la no pseudo-código. Como ele estava anotado na classe?

  10. Raphael Lacerda 29/04/2015 at 11:19 #

    Galera, valeu pelos parabéns!!!!

    respondendo a todos:

    @kalil… vou falar de outras diferenças!! Acompanhe aí!

    @Rasa … claaaarro! vou falar sim! foi o principal motivo da migração. Será o terceiro Post… ainda vem um para falar sobr weaving

    @ranlive .. vou falar sobre isso no próximo!!

    @gilmar… me passa o link depois! @lacerdaph

    @bruno .. então, estava sem nenhuma anotação

  11. Junior 29/04/2015 at 11:52 #

    Raphael! Parabéns.

    Estou ansioso por ler os próximos posts.

    Quanto à “Devo declarar no persistence.xml?”, utilizando qualquer implementação, não basta declarar false no persistence.xml, para que ele identifique as entidades automáticamente?

    Abraço.

  12. Junior 29/04/2015 at 11:53 #

    exclude-unlisted-classes como false

  13. Neil 29/04/2015 at 14:18 #

    “Late JDO” ? JDO 3.1 was released a month ago, and JDO 3.2 is being developed.
    DataNucleus seemingly exists and is used by many projects I know of, and it even supports JPA 2.1 … whilst OpenJPA and Batoo don’t … yet they get a mention

  14. Bruno Roberto Gonçalves 29/04/2015 at 15:17 #

    Parabéns Raphael, eu gosto bastante do EclipseLink.
    No EclipseLink é possível descobrir as classes com anotação @Entity. Em JavaEE isso é automático mas em JavaSE é necessário marcar a tag flag exclude-unlisted-classes dentro do persistence.xml como “false”.

  15. Raphael Lacerda 29/04/2015 at 19:22 #

    @Bruno e @Junior

    Isso aí mesmo.. JavaEE tranquilo, SE tem que fazer configurações a mais

    uma delas
    exclude-unlisted-classes como false

    Por isso até coloquei em negrito o SE

    hehehe!

    E valeu por completar o post

  16. Raphael Lacerda 29/04/2015 at 19:29 #

    Hey @Neil, revealing comments, at least for me!!

    The first JSR about JDO is from December 2004. I honestly didn’t know that it is still under updates.Nice to know about it.
    And i didn’t know about http://www.datanucleus.org/ either. Could you tell us a little bit more about the project?

  17. Neil 30/04/2015 at 03:35 #

    @Raphael,
    I have no connection to DataNucleus, except that I have used it (and its predecessor JPOX) since 2007. It’s the JDO “reference implementation” and has been since its start, and has supported JPA since it came out also. Their usage page shows plenty of companies using it (many with JDO I think, but still quite a few with JPA), and it supports ALL versions of JPA, and is Apache licensed. It allows persistence to way more datastores than those you mention.

    Sadly the IT world is very introverted and sticks to what large corporations push at them (Hibernate and EclipseLink) so maybe for that reason it gets less opportunities. Give it a try maybe

  18. Rafael Ponte 30/04/2015 at 10:03 #

    Excelente post, Raphael! Ah, parabéns, meu amigo!

    Mesmo com a especificação da JPA ainda existem diversas diferenças entre Hibernate e EclipseLink e isso pode impactar na migração. O SQL gerado entre eles pode ser bem diferente dependendo da consulta, o que pode impactar diretamente na performance; se brincar na migração é possível cair no problema do Select N+1.

    No mais, eu nunca trabalhei com EclipseLink, se fosse utilizá-lo hoje em dia seria mais por conta do multi-tenancy. Mas claro, pelo que já li ele tem várias features bem interessantes de usar que não existem no Hibernate! No fim das contas, é um trade-off.

    Um abraço e parabéns em dobro pelo artigo e pelo aniversário <3

  19. Fabrício 04/05/2015 at 16:45 #

    Parabéns pelo post, Raphael!

    Gostaria, se possível, de acrescentar uma pergunta: no EclipseLink, diferente do Hibernate,
    é possível persistir uma classe que seja declarada como final? Se não me engano, o Hibernate
    não permite isto…

    Agradeço a atenção!

  20. Rodrigo Ferreira 06/05/2015 at 08:42 #

    @Fabrício,

    Na verdade a própria especificação JPA diz que uma entity não deve ser final:
    “The entity class must not be final. No methods or persistent instance variables of the entity class may be final.”

  21. Diego Fernandes 12/05/2015 at 10:27 #

    Muito bom!!!!

  22. Marlon Falzetta 12/05/2015 at 10:55 #

    Post bacana. Aguardo os próximos.

    Felicidades pelo aniversário.

  23. Raphael Lacerda 13/05/2015 at 14:38 #

    É isso aí Ponte..

    Multitenancy vem no terceiro artigo da série.

    O próximo é weaving e mapeamentos….

  24. evandro silva 28/04/2016 at 12:03 #

    Excelente Post! Parabéns.

Deixe uma resposta