Introduction
Neste tutorial, vamos discutir Hibernate e o Java Persistence API (JPA) – com foco nas diferenças entre eles.
Vamos começar por explorar o que é o JPA, como ele é usado e os conceitos centrais por trás dele.
Então, vamos dar uma olhada em como Hibernate e EclipseLink se encaixam na figura.
Mapeamento Relacional a Objetos
Antes de mergulharmos no JPA, é importante entender o conceito de Mapeamento Relacional a Objetos – também conhecido como ORM.
O mapeamento Relacional a Objetos é simplesmente o processo de persistir em qualquer objeto Java diretamente em uma tabela de banco de dados. Normalmente, o nome do objeto a ser persistido torna-se o nome da tabela, e cada campo dentro desse objeto torna-se uma coluna. Com a tabela configurada, cada linha corresponde a um registro na aplicação.
Uma Introdução ao JPA
O Java Persistence API, ou JPA, é uma especificação que define o gerenciamento de dados relacionais em uma aplicação Java. A API mapeia um conjunto de conceitos que define quais objetos dentro da aplicação devem ser persistidos, e como devem persistir.
É importante notar aqui que JPA é apenas uma especificação e que precisa de uma implementação para funcionar – mas mais sobre isso mais tarde.
Agora, vamos discutir alguns dos conceitos centrais de JPA que uma implementação deve cobrir.
3.1. Entity
A classe javax.persistence.Entity define quais objetos devem ser persistidos no banco de dados. Para cada entidade persistida, o JPA cria uma nova tabela dentro do banco de dados escolhido.
Além disso, todas as entidades escolhidas devem definir uma chave primária denotada pela anotação @Id. Juntamente com a anotação @GeneratedValue, definimos que a chave primária deve ser gerada automaticamente quando o registro é persistido no banco de dados.
Vejamos um exemplo rápido de uma entidade descrita pelo JPA.
@Entitypublic class Car { @GeneratedValue @Id public long id; // getters and setters}
Remember, isto atualmente não terá efeito na aplicação – o JPA não fornece nenhum código de implementação.
3.2. Persistência de campo
Outro conceito central do JPA é persistência de campo. Quando um objeto em Java é definido como uma entidade, todos os campos dentro dele são automaticamente persistidos como colunas diferentes dentro da tabela de entidades.
Se houver um campo dentro de um objeto persistido que não queremos persistir no banco de dados, podemos declarar o campo transitório com a anotação @Transient.
3.3. Relationships
Next, JPA especifica como devemos gerenciar as relações entre diferentes tabelas de banco de dados dentro da nossa aplicação. Como já vimos, o JPA lida com isso com anotações. Existem quatro anotações de relacionamentos que precisamos ter em mente:
- @OneToOne
- @OneToMany
- @ManyToOne
- @ManyToMany
- @ManyToMany
Vejamos como isto funciona:
@Entitypublic class SteeringWheel { @OneToOne private Car car // getters and setters}
No nosso exemplo acima, a classe SteeringWheel descreve uma relação de um para um com a nossa classe Carro de antes.
3.4. Entity Manager
Finalmente, a classe javax.persistence.EntityManager especifica operações de e para o banco de dados. O EntityManager contém operações comuns de Create, Read, Update and Delete (CRUD) que são persistidas para o banco de dados.
JPA Implementations
Com a especificação JPA definindo como e o que devemos persistir, agora precisamos escolher um provedor de implementação para fornecer o código necessário. Sem esse provedor, precisaríamos implementar todas as classes relevantes para estar em conformidade com o JPA, e isso dá muito trabalho!
Existem muitos provedores para escolher, com cada um apresentando seus próprios prós e contras. Ao tomar uma decisão sobre qual usar, devemos considerar alguns dos seguintes pontos:
- Madurecimento do projeto – há quanto tempo o provedor está por perto, e quão bem documentado ele está?
- Subprojectos – o fornecedor tem algum subprojecto útil para a nossa nova aplicação?
- Suporte comunitário – há alguém para nos ajudar quando acabamos com um bug crítico?
- Benchmarking – qual é o desempenho da implementação?
>
Embora não vamos aprofundar no benchmarking de diferentes provedores JPA, o JPAB (JPAB – JPA Performance Benchmark) contém uma visão valiosa sobre isso.
Com isso fora do caminho, vamos dar uma breve olhada em alguns dos principais provedores de JPA.
Hibernate
No seu núcleo, Hibernate é uma ferramenta de mapeamento objeto-relacional que fornece uma implementação de JPA. Hibernate é uma das mais maduras implementações de JPA ao redor, com uma enorme comunidade apoiando o projeto.
Ele implementa todas as classes javax.persistence que vimos anteriormente no artigo, assim como fornece funcionalidades além do JPA – ferramentas Hibernate, validação e busca. Embora essas APIs específicas de Hibernate possam ser úteis, elas não são necessárias em aplicações que requerem apenas a funcionalidade base do JPA.
Vamos dar uma olhada rápida no que Hibernate oferece com a anotação @Entity.
Apesar de cumprir o contrato JPA, @org.hibernate.annotations.Entity adiciona metadados adicionais que vão além da especificação do JPA. Fazendo isso, permite a persistência de entidades de afinação fina. Por exemplo, vejamos algumas anotações oferecidas por Hibernate que estende a funcionalidade de @Entity:
- @Table – permite-nos especificar o nome da tabela criada para a entidade
- @BatchSize – especifica o tamanho do lote ao recuperar entidades da tabela
Também vale a pena notar algumas das características extras que o JPA não especifica, que podem se mostrar úteis em aplicações maiores:
- Configurações CRUD customizáveis com as anotações @SQLInsert, @SQLUpate e @SQLDelete
- Suporte para exclusão suave
- Entidades imutáveis com a anotação @Immutable
Para um mergulho mais profundo na persistência de Hibernate e Java – vá para a nossa série de tutoriais de persistência Spring.
EclipseLink
EclipseLink, construído pela Eclipse Foundation, fornece uma implementação JPA open-source. Adicionalmente, o EclipseLink suporta uma série de outros padrões de persistência como a Arquitectura Java para XML Binding (JAXB).
Simplesmente colocado, em vez de persistir num objecto para uma linha de base de dados, o JAXB mapeia-o para uma representação XML.
Next, comparando a mesma implementação de anotação @Entity, vemos que o EclipseLink oferece novamente diferentes extensões. Embora não haja anotação para @BatchSize como vimos anteriormente, o EclipseLink oferece outras opções que o Hibernate não oferece.
Por exemplo:
- @ReadOnly – especifica que a entidade a ser persistida é read-only
- @Struct – define a classe a mapear para uma base de dados do tipo ‘struct’
Para ler mais sobre o que o EclipseLink tem para oferecer, vá até ao nosso guia sobre o EclipseLink com Spring.
Conclusion
Neste artigo, vimos o Java Persistence API, ou JPA.
Finalmente, exploramos como ele difere do Hibernate e do EclipseLink.