Alura > Cursos de Programação > Cursos de Java > Conteúdos de Java > Primeiras aulas do curso Persistência com JPA: Hibernate

Persistência com JPA: Hibernate

Começando com JPA - Apresentação

Olá, pessoal! Boas-vindas ao curso Persistência com JPA: Introdução ao Hibernate. Meu nome é Rodrigo Ferreira e serei o instrutor que acompanhará vocês durante este treinamento.

Então, neste treinamento aprenderemos sobre a JPA, "Java Persistence API", poque ela veio para substituir - digamos assim - a JDBC, e aprender a utilizá-la na prática.

Nosso treinamento será dividido em duas partes, e nesta parte discutiremos alguns tópicos. O primeiro é Motivação para utilizar JPA: o que é a JPA, por que foi criada e para resolver quais problemas. Enfim, a intenção é saber a utilização e motivação principal da JPA. O segundo é Download e Configurações: como fazer para baixar a JPA e utilizá-la no projeto (usando o hibernate como implementação).

O terceiro é Arquivo persistence.xml: se refere às configurações. Aprenderemos para que serve o aquivo persistence.xml e como configurar os elementos da JPA nesse arquivo. O quarto é Mapeamento de entidades: classes que mapearão a tabela no banco de dados, ou seja, aprenderemos o que são essas entidades e como mapear de acordo com o banco de dados.

O quinto é Mapeamento de relacionamentos: uma entidade que precisa se relacionar com outra, num relacionamento um para um, um para muitos, muitos para muitos, enfim, aprenderemos como fazer o mapeamento correto utilizando a JPA.

O sexto é Ciclo de vida de uma entidade: quando mandamos salvar no banco de dados ou quando fazemos uma consulta, o que acontece com a entidade se mexemos no atributo, se será propagado para o banco de dados. O sétimo e último tópico é Consultas com JPQL: a JPQL é uma linguagem parecida com a SQL, mas que conta com a orientação a objetos.

Então, estes são os principais tópicos que trataremos nesta primeira parte do treinamento de JPA. No primeiro vídeo, conheceremos um pouco da motivação e ideia da JPA. Vejo vocês lá!!

Começando com JPA - JDBC e seus problemas

Para começar o nosso treinamento de JPA, vamos discutir um pouco da motivação, isto é, para que a JPA foi criada - para resolver quais problemas. Além disso, discutiremos sobre o hibernate e outras implementações.

Neste vídeo, também trataremos do JDBC, que é a tecnologia padrão do Java para acessar o banco de dados relacionais. Quem aprendeu a programar em Java, provavelmente, quando for desenvolver sistemas, precisará fazer o acesso ao banco de dados.

Para fazer o acesso do Java com um banco de dados, por exemplo, uma SQL, Oracle, ou qualquer outro banco de dados, a tecnologia padrão utilizada é o JDBC. O Java nasceu em 1995, em 1997 veio o JDBC.

Antes do JDBC, se quiséssemos acessar um banco de dados em Java, era necessário aprender tecnologias complexas de socket e fazer tudo manualmente: abrir uma conexão com banco de dados e fazer toda comunicação utilizando o protocolo específico daquele banco de dados. Era muito trabalhoso e complicado.

O JDBC veio para facilitar esse processo. Ele nada mais é do que uma especificação para fazer acesso a bancos de dados relacionais no Java. Portanto, se trata de uma camada de abstração para acessar, do código Java, o banco de dados, independente de qual seja o protocolo. Em outras palavras, o JDBC veio como uma camada para simplificar o acesso e facilitar fazer trocas de bancos de dados.

A partir disso, não é mais necessário conhecer o protocolo MySQL, do Oracle, saber os detalhes técnicos, nem ficar abrindo o socket e fazendo uma comunicação manual com o banco de dados, basta utilizar o JDBC.

Quem já estudou o JDBC (na Alura temos treinamento de JDBC), sabe que precisamos ter um driver. Esse driver é um JAR, um arquivo com as classes do banco de dados. Ou seja, ele é a implementação do banco de dados em cima da JDBC.

Então, para acessar o MySQL, é necessário baixar o driver do MySQL. Para trocar o banco de dados - usar o PostgreSQL, por exemplo - trocamos o JAR baixando o driver do PostgreSQL, que é outro JAR. Ambos estão implementando o JDBC, de maneira que, no código, o impacto é mínimo.

Ao mudar de um banco de dados para outro, temos poucas mudanças no código. Trocamos basicamente as configurações, mas, a grande parte do código que está fazendo a comunicação com o banco de dados continua igual. Isso facilita muito por não nos prendermos a um só fornecedor, a um banco de dados.

Para não ficar com o código do JDBC espalhado em vários pontos da aplicação, um padrão de projeto bastante utilizado é o "DAO", Data Access Object. Com ele, é possível isolar toda a API do JDBC dentro de uma única classe - de uma única camada - para não ficar com os códigos de Connection, ResultSet, que são classes complicadas do JDBC, espalhadas pela aplicação.

Basicamente, temos alguma classe na aplicação, um Controller, uma Service ou algo do gênero. Nesta classe está contida a lógica de negócios, e, nessa lógica, precisamos acessar o banco de dados. Ou seja, não instanciamos, não chamamos as classes do JDBC, e, sim, uma classe DAO. É na classe DAO que está isolado - abstraído, encapsulado - o código do JDBC, é ela também que faz a ponte com o banco de dados. Então, existia uma divisão de responsabilidades na aplicação.

Olhando de fora da classe DAO, existiria algo aproximadamente assim:

public class CadastroProdutoService {

    private ProdutoDao dao;

        public CadastroProdutoService(ProdutoDao dao) {
            this.dao = dao;
        }

        public void cadastrarProduto(Produto produto) {
            // regras de negocio...

                this.dao.cadastrar(produto);
        }

Imagine que temos um CadastroProdutoService. Precisaríamos de uma classe DAO e de um método, como CadastrarProduto(). Depois receberíamos o objeto produto. Teríamos também as regras de negócio, validação, cálculos, e então chamaríamos dao.cadastrar.

Olhando de fora, não dá para saber como a classe DAO está funcionando, se ela está usando JDBC, se a persistência é em banco de dados, se é em arquivo, em memória, em um serviço externo, não sabemos se é MySQL, Oracle.

O código está bem fácil de usar: chamamos a DAO, depois o método cadastrar(), passamos o objeto produto, e pronto, não ficamos presos a como foi implementado o método cadastrar(). Assim, não temos acesso à API do JDBC, ela fica bem isolada. Por fora, o código fica bem bonito, mas, por dentro da classe DAO, temos um problema.

Em classes DAO, usando JDBC, acabamos tendo um código bem complicado, porque precisamos usar a API do JDBC que é uma API bastante antiga do Java (foi criada em 1997), com bastante verbosidade, e fez com que as pessoas desenvolvessem certa aversão ao Java, pela impressão de que nele é tudo burocrático, complexo.

Então, é necessário lidar com classes, como PreparedStatement, connection, ResultSet. Também é necessário fazer tryCatch(), porque elas lançam checked exception. Além disso, precisamos montar uma SQL manualmente, usar o PreparedStatement para não ter o problema do SQL Injection. Tudo isso deixa o código um pouco complicado.

Esse tipo de código JDBC, embora funcione, apresenta algumas desvantagens que fizeram com que as pessoas pensassem em outras alternativas mais simples. O JDBC tem dois grandes problemas que motivaram o surgimento de tecnologias como o Hibernate e a JPA. O primeiro problema é o Código muito verboso. Por exemplo, para salvar um produto no banco de dados, precisamos de cerca de 30 linhas de código.

Em um código tão grande, é difícil e demorado fazer manutenção. Às vezes, é necessário montar uma Query nativa do banco de dados, e o código vai ficando cada vez mais difícil de entender e de fazer manutenção. Esse é um grande problema, e nem é o pior.

O segundo problema é o Alto acoplamento com o banco de dados. Quando trabalhamos com o JDBC, temos um acoplamento muito forte com o banco de dados. Significa que, qualquer mudança no banco de dados gera um impacto muito forte na aplicação. Por exemplo, se trocamos o nome da tabela, de alguma coluna ou qualquer outro detalhe desses, acabamos impactando a aplicação e teremos que mexer na classe DAO.

O problema é que, pode acontecer de, por exemplo, ao renomearmos a tabela de produto, pode ser que - além da classe ProdutoDao- existam outras classes DAO que façam JOIN com a tabela produto. Ou seja, precisaremos procurar todos os lugares que estão referenciando tabela produto e fazer esse rename. Isso nos leva a um alto acomplamento com banco de dados. Qualquer mudança de um lado, gera impacto grande do outro.

Esses são os dois principais problemas que as pessoas começaram a perceber no JDBC e, a por conta deles, aprimoraram ideias de como reduzir o impacto que esses dois problemas geram. Foi desse processo que surgiu a JPA. No próximo vídeo, discutiremos com calma como foi a criação da JPA e como ela resolveu os problemas do JDBC. Vejo vocês lá!! Abraços!!

Começando com JPA - Hibernate e JPA

Já discutimos um pouco sobre o JDBC e os principais problemas que Devs passaram a identificar conforme desenvolviam as aplicações. A existência desses problemas foi, justamente, o que motivou as pessoas a buscarem alternativas, tecnologias que fossem mais simples para fazer a ponte, a ligação com o banco de dados.

Dentre essas tecnologias, surgiu uma biblioteca que ficou bem famosa, chamada Hibernate. O Hibernate foi lançado em 2001 e criado por Gavin King, que tinha como ideia, justamente, tentar simplificar o JDBC. Supondo que temos uma aplicação web, desktop, é precisamos fazer o acesso ao banco de dados, mas não gostamos muito do modelo do JDBC, porque o código fica muito verboso, complexo, muito acoplado ao banco de dados.

Gavin King começou a pensar em uma maneira de simplificar o código e criou essa biblioteca (Hibernate) e em 2001 fez o lançamento. Mas, se percebermos, ela não tem nada a ver com o Java, ela é uma biblioteca que surgiu no mercado e que ele distribuiu gratuitamente. Assim nasceu o Hibernate, uma biblioteca famosa por fazer persistência no banco de dados como alternativa ao JDBC e ao EJB 2.

Na época existia a versão 2.0 do EJB 2, e era uma tecnologia bem complicada de se trabalhar. A ideia do EJB era simplificar o acesso remoto, para ter uma aplicação distribuída (cliente - servidor) e também simplificar alguns detalhes de infraestrutura, como controle transacional, segurança e outros.

Também havia a parte de persistência junto da EJB, mas ela utilizava a JDBC, era um modelo um pouco mais complexo e que favorecia muito a remotabilidade, então, qualquer chamada que se fazia era uma chamada remota, isso tinha um custo de performance. Enfim, vários problemas surgiram e vários padrões também foram criados para resolver esse problema da EJB 2 na parte de persistência. Isso também motivou o Gavin King a criar o Hibernate.

Posteriormente, Gavin King foi contratado pela Red Hat, para continuar os trabalhos no Hibernate. Portanto, o Hibernate é uma teconologia que pertence à JBoss (Red Hat). O Gavin King trabalhou na JBoss e lá deu continuidade ao Hibernate e a outros projetos.

Conforme o tempo passou, foram surgindo novas versões do Hibernate, ele ficou famoso no mundo inteiro, todas as pessoas que trabalhavam com Java queriam utilizar Hibernate nos projetos para não ter que usar a EJB 2 e JDBC. Enfim, virou um projeto mega popular, e foi evoluindo, foram surgindo versões posteriores com novos recursos.

Como se tratava de uma biblioteca do mercado, surgiram também concorrentes. Portanto, estamos falando de uma biblioteca que está famosa, popular, logo, outras bibliotecas passaram a copiar, mas fazendo de outra forma.

Isso gerou um velho problema: imagine que, como Devs, estamos usando uma biblioteca, queremos trocar para outra (uma biblioteca de mercado). Para fazer isso, não é só trocar os JARs, as dependências do projeto, isso causará um impacto considerável no código.

Para todo o código em que estávamos usando o Hibernate, será necessário trocar para essa nova biblioteca, já que são outras classes, outros imports. Se o nosso projeto fosse grande, complexo, pensaríamos duas vezes antes de trocar. A Sun, a Oracle, o Java, não gostam disso, porque significa estar preso a um fornecedor.

Posteriormente, uma padronização da biblioteca foi criada, do modelo de persistência, que ficou conhecida como ORM (Object Relational Mapping) em Java, com a intenção de fazer o mapeamento, a ponte entre o mundo da "orientação a Objetos" com o "relacional" do banco de dados.

Existem esses dois mundos distintos, e a classe DAO ficava um tanto complexa, porque estávamos fazendo essa ponte entre o mundo "orientação a objetos" e mundo orientado ao "modelo relacional" do banco de dados. O Java criou uma especificação chamada de JPA, Java Persistence API, que é a especificação para padronizar o mapeamento a objeto relacional no mundo Java.

Com a JPA, criou-se um padrão para que não ficássemos reféns de uma biblioteca. Os frameworks, as bibliotecas, começaram a implementar a JPA. No código, ao invés de fazer os imports das classes e interfaces do Hibernate, passou-se a fazer a da JPA, que é a especificação.

Portanto, a biblioteca se tornava uma implementação, e, para trocar de implementação, só precisávamos trocar os JARs, uma ou outra configuração, mas o código, em si, continuava intacto, inalterado, por não depender de uma implementação.

A JPA só foi lançada em 2006, então, de 2001 a 2006, precisávamos utilizar o Hibernate ou os seus concorrentes sem a abstração da especificação. O Hibernate foi evoluindo, foram surgindo novos recursos e depois isso foi incorporado na versão 2.0 da JPA, lançada em 2009.

O Hibernate, em 2010, um ano depois, lançou a versão 3.5.0, que era compatível com a JPA 2.0. Portanto, se quiséssemos usar a JPA 2.0, podíamos utilizar o Hibernate como implementação. Se posteriormente quiséssemos trocar por outras implementações, seria fácil, não causaria impacto no projeto inteiro. Essa é a grande vantagem de se utilizar uma especificação ao invés de usar diretamente uma implementação e ficar preso a ela.

No mercado, ficamos com algo parecido com esse diagrama, em que uma seta sai de cada um dos três retângulos (1. Hibernate, 2. EclipseLink, 3. OpenJPA) e aponta para o retângulo que está acima deles: JPA. Ou seja, temos em cima a JPA, que é a especificação, e temos também várias implementações, como o Hibernate, o EclipseLink, OpenJPA, dentre outras implementações. Essas são as três principais da JPA.

Para trabalharmos com a JPA, temos que escolher uma dessas implementações. Isto é, não se usa a JPA "pura", porque ela é só a "casca", a abstração. Nós precisamos de alguém que implemente os detalhes, quem faz esse trabalho são bibliotecas como o Hibernate.

Como o Hibernate foi a primeira biblioteca, ele foi quem começou esse movimento, por isso acabou se tornando a biblioteca padrão, a mais utilizada, mais popular como implementação da JPA. Mas, nada nos impede de usar outras implementações. Se todas estão seguindo a JPA, todas precisam atender ao que está descrito na especificação da JPA.

Além disso, podemos trocar uma implementação pela outra, e tudo que estiver na especificação vai funcionar. Só teremos problemas se estivermos utilizando algo que é específico da implementação. Às vezes, o Hibernate costuma fazer isso, segue a JPA, mas tem alguns recursos que são específicos dele.

Se utilizarmos, está tudo certo, estamos ganhando esse novo recurso. Mas, o lado negativo, já que esse recurso é específico do Habernate. Então, por exemplo, se quisermos trocar o Hibernate pelo EclipseLink, perderemos essa funcionalidade. Assim, temos que tomar esse cuidado e avaliar se vale mesmo a pena essa dependência.

O EclipseLink é a implementação de referência da JPA. Sempre que surge uma nova versão da JPA, o EclipseLink já está implementando, pois, é nele que são feitos os testes e ele sai com a nova versão da JPA. Ele é a implementação de referência, porém, o Hibernate é a principal, a mais popular no mercado. Por isso, neste curso trabalharemos com o Hibernate como implementação da JPA.

Fechamos essa parte de motivação. Nosso objetivo era apenas discutir um pouco e entender o que é a JPA, porque ela foi criada, de que nasceu, o que é o Hibernate, qual a diferença de Hibernate e JPA. Agora que alinhamos esses conhecimentos, no próximo vídeo, partiremos para a prática. Começaremos a aprender como utilizar a JPA e Hibernate no projeto.

Vejo vocês lá!! Abraços!!

Sobre o curso Persistência com JPA: Hibernate

O curso Persistência com JPA: Hibernate possui 146 minutos de vídeos, em um total de 43 atividades. Gostou? Conheça nossos outros cursos de Java em Programação, ou leia nossos artigos de Programação.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda Java acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas