• Nenhum resultado encontrado

A JPA vai mais além do que um simples executar de SQLs

No documento Casa do Código. Agradecimentos (páginas 82-87)

mos o porscheDetached, visto que esse mesmo contexto já possuía a instância porscheGerenciado.

Se a EntityManagerpermitisse duas instâncias gerenciadas de Modelocom id=1, qual seria o updateno momento do commitda transação? Qual objeto considerar?

Para que não haja dúvidas, a EntityManagertem sempre um único objeto gerenciado do mesmo tipo e com o mesmo id. Por esse motivo, em vez de passar a instância porscheDetachedpara gerenciado, como ela já tinha uma instância ge- renciada, porscheGerenciado, a EntityManagerusou esse objeto como base e jogou as alterações feitas no objeto detached em cima do gerenciado.

É como se as alterações feitas nos Porsches fossem realizadas no objeto porscheGerenciado. Na verdade isso foi feito dentro do método merge. Como a instância está gerenciada e foi alterada, no momento do commitela será sincro- nizada com o banco, ou seja, o comando update do SQL será feito.

4.4

A JPA vai mais além do que um simples executar

de SQLs

Acabamos de perceber que a JPA faz mais coisas além de executar SQLs. Ela mantém uma organização entre os nossos objetos através desse controle do ciclo de vida deles. É importantíssimo entender todo esse ciclo para que seja possível aprender outros pontos primordiais da JPA.

Capítulo 5

Como mapear tudo... ou nada!

A partir de agora veremos como mapear nosso modelo Orientado a Objetos para o relacional. Normalmente, existe um fator principal que influencia bastante no nosso mapeamento, que é o uso de um banco de dados novo ou de um existente.

Quando vamos criar uma aplicação nova, que não irá reutilizar nenhum banco existente, costumamos ter maior liberdade para apenas refletir no banco as decisões de design das nossas classes. Com isso, geralmente o mapeamento é mínimo, e utili- zamos muito os comportamentos padrões da JPA.

Outra situação é quando precisamos mapear um banco de dados existente, es- pecialmente quando segue padrões de nomenclatura e de estrutura provenientes de modelo Entidade-Relacionamento tradicional. Com isso podemos entender que as entidades geralmente terão sua chave primária definida por um conjunto de atribu- tos que, combinados, torna a entidade única. Por exemplo, vamos considerar a classe abaixo representando a venda de um automóvel.

Casa do Código

Figura 5.1: Classe venda

A respectiva tabela responsável por armazenar no banco de dados os dados dessa classe pode ser algo como:

Figura 5.2: DER com nomes abreviados e chave composta

Podemos notar que foi definida uma chave composta que identifica uma venda como única. No exemplo, identificamos que uma venda é representada pelo código do automóvel vendido, pelo código de quem vendeu e pelo código de quem com- prou, sendo que esses códigos são chaves estrangeiras que, combinadas, formam a chave primária. Repare também no nome da tabela e nos nomes das colunas, que geralmente seguem um padrão parecido com o apresentado, em que muitas vezes as palavras são abreviadas.

Agora vamos comparar com a tabela que teríamos se utilizássemos apenas as convenções da JPA.

Casa do Código Capítulo 5. Como mapear tudo... ou nada!

Figura 5.3: DER com nomenclatura padrão JPA

São notórias as mudanças na nomenclatura, que agora reflete os mesmos no- mes utilizados na classe. Mas talvez a principal diferença seria utilizar uma chave primária artificial em vez da chave que utiliza os atributos já existentes na tabela.

Claro que nem sempre essa abordagem vai gerar chaves compostas. Por exemplo, no cadastro de uma pessoa, a chave primária poderia ser o CPF ou o e-mail. Mas o fato é que a abordagem da chave artificial autoincrementada tem ganhado muito espaço.

Nesse capítulo vamos ver como trabalhar com o mapeamento, para que ele se adeque da melhor maneira possível à nossa necessidade de banco de dados, seja ela mais próxima das convenções da JPA, seja ela totalmente customizada.

5.1

Definições de entidade

Como já vimos no capítulo2, geralmente temos a anotação @Entitysobre a classe cujas informações dos objetos gostaríamos de persistir em um banco de dados. Elas são o que chamamos de entidades.

Além da anotação @Entity, precisamos registrar nossa classe no arquivo persistence.xml, como a seguir.

<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> 75

5.1. Definições de entidade Casa do Código <persistence-unit name="default" transaction-type="RESOURCE_LOCAL">

<class>facesmotors.entities.Automovel</class> <properties> ... </properties> </persistence-unit> </persistence>

Esse passo habilita a entidade na persistence-unitdefault.

Pela especificação da JPA, ao utilizarmos um servidor de aplicações Java EE, não precisaríamos especificar as entidades no persistence.xmldesde que tivésse- mos apenas uma persistence-unit. Na prática, as implementações acabam es- tendendo isso para o ambiente JavaSE, como o que estamos utilizando. Sendo assim, a declaração das entidades através do persistence.xmlé opcional na nossa apli- cação.

Caso tenhamos mais de umapersistence-unit, declaramos todas as entida- des em sua respectiva persistence-unit. No entanto, ele continuará tentando carregar as classes automaticamente, e com isso, uma persistence-unitpode ter classes carregadas de outra. Uma confusão só!

Para evitarmos que se tente carregar automaticamente entidades que não deve- riam, já que não foram listadas no persistence.xml, utilizamos a configuração <exclude-unlisted-classes>com o valor true, assim a JPA não tentará atri- buir automaticamente entidades na persistence-uniterrada.

Para exemplificar a existência de mais de uma persistence-unit, considere as entidades Funcionarioe PrestadorServico. O primeiro se refere aos fun- cionários da empresa e tem seus dados em um banco de dados. O segundo se refere a um prestador de serviço ou funcionário terceirizado e possui seus dados armaze- nados em outro banco de dados. Nesse caso, a configuração do persistence.xml ficaria como a seguir:

<persistence...> ...

<persistence-unit name="funcionarios"

transaction-type="RESOURCE_LOCAL"> <class>sistemarh.entities.Funcionario</class> <exclude-unlisted-classes>true</exclude-unlisted-classes> <properties> ... </properties>

Casa do Código Capítulo 5. Como mapear tudo... ou nada! </persistence-unit>

<persistence-unit name="terceirizados"

transaction-type="RESOURCE_LOCAL"> <class>sistemarh.entities.PrestadorServico</class> <exclude-unlisted-classes>true</exclude-unlisted-classes> <properties> ... </properties> </persistence-unit> </persistence>

E com isso nenhuma classe é carregada sem que indiquemos que ela realmente deve ser carregada.

5.2

Faça atributos não serem persistidos com o

No documento Casa do Código. Agradecimentos (páginas 82-87)