Sunteți pe pagina 1din 8

Relacionamento entre Entidades

Sempre que trabalhamos com uma conta bancria, realizamos pagamentos, recebemos salrios, transferimos dinheiro para outras contas e assim por diante. As operaes que realizamos em nossas contas so tambm conhecidas como movimentaes, que a partir de agora vamos representar em nosso sistema. Cada Movimentacao deve ter um valor movimentado, tipo, data de realizao, descrio e tambm uma Conta vinculada.

Relacionando a Movimentao com uma Conta


Vamos criar uma nova entidade chamada Movimentacao. Selecionamos o package, pressionamos ctrl + N e escolhemosClass. Na caixa de dilogo, digitamos o nome da classe, Movimentacao. Ento ela ficar no pacotebr.com.caelum.financas.modelo. Como vimos no capitulo 2, no podemos esquecer que precisamos das

anotaes @Entity para definir a entidade, juntamente com @Id e @GeneratedValue para a chave primria. Todas do pacote javax.persistence.

@Entity public class Movimentacao { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; }

O prximo atributo representa o valor da movimentao. A primeira ideia seria usar o tipo double para represent-lo, porm o double no tem a preciso suficiente. Ou seja, no deve ser utilizado para guardar valores financeiros. Utilizaremos

entoBigDecimal para no perder informaes preciosas de um nmero com ponto flutuante.


@Entity public class Movimentacao {

@Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private BigDecimal valor;

Mapeando datas e enumeraes


Continuaremos com a definio do tipo da movimentao. O tipo poderia ser uma String, onde guardaramos ENTRADA ou SAIDA como valor. Infelizmente uma String pode receber qualquer valor, no s esses dois, assim perderamos a confiabilidade dos dados. Precisamos de uma soluo melhor. Como alternativa poderamos declarar o atributo como intonde 0 ENTRADA e 1 SAIDA. Mas a teramos o mesmo problema anterior, pois esse tipo pode guardar muito mais valores, incluindo valores negativos, alm do mais exigiria uma documentao sobre o significado dos nmero. Para definir o tipo da movimentao de forma simples e consistente, sem a necessidade de validaes e documentao, podemos utilizar um recurso muito interessante, introduzido no Java 5, que nos permite criar objetos que representem constantes. As Enums. Dessa forma, vamos criar uma Enum chamada TipoMovimentacao que define duas constantes: ENTRADA e SAIDA.
public enum TipoMovimentacao {

ENTRADA, SAIDA; }

Como agora o atributo uma Enum, precisamos anot-lo com @Enumerated. Alm disso, queremos mapear no banco de dados como sendo do tipo String. Precisamos ento

definir o parmetro EnumType para STRING. Isso significa que no registro do banco ficar gravado o varchar: SAIDA ou ENTRADA.
@Entity public class Movimentacao {

// demais atributos omitidos

@Enumerated(EnumType.STRING) private TipoMovimentacao tipoMovimentacao;

No Java, quando trabalhamos com datas, normalmente usamos o tipo Calendar. Mas como cada banco lida de formas diferentes com dados desse tipo, precisamos dizer para o JPA qual a forma que queremos armazenar a data no banco. Devemos ento primeiro anotar o atributo com @Temporal, depois definir o parmetro de preciso desejado (TemporalType). Aqui temos 3 opes:

DATE: somente a data, sem a hora; TIME: somente a hora, sem data; TIMESTAMP: tanto data quanto hora. No nosso caso guardamos apenas a data, sem a hora:
@Entity public class Movimentacao {

// demais atributos omitidos

@Temporal(TemporalType.DATE) private Calendar data;

Por fim, falta a descrio da movimentao. Aqui no h novidade, ela ser do tipo String. Tambm j vamos gerar os getters e setters para cada atributo.

Definindo a relacionamento

cardinalidade

do

O JPA sempre tentar mapear os tipos do Java para os tipos adequados no banco de dados. Dessa forma, ao criar um atributo do tipo String no Java, ele ser mapeado para varchar no MySQL. Isso vale para os principais tipos do Java.

No entanto, nossa entidade Movimentacao ter um atributo Conta. Como o JPA mapear esse atributo no banco de dados? Um varchar ou um int? O que queremos mapear um relacionamento entre as entidades, que no banco dever ser refletido por uma chave estrangeira (Foreign Key). A nica informao que precisamos dizer qual a cardinalidade da Movimentacao em relao Conta. Na nossa aplicao, diversas movimentaes possuem uma nica conta. Esse relacionamento de muitos para um. Essa cardinalidade ns representamos no cdigo Java com a anotao @ManyToOne. Vamos ento anotar nosso atributo conta:

@Entity public class Movimentacao {

// demais atributos omitidos

@ManyToOne private Conta conta;

// getters e setters omitidos }

Com isso, a implementao do JPA gerar uma nova coluna na tabela Movimentacao que se chamar conta_id. Tambm vamos gerar o getter e setter para o atributo conta.

ATENO: No podemos esquecer de registrar a nova entidade Movimentacao no arquivo persistence.xml. Vamos editar o arquivo persistence.xml e acrescentar

na persistence-unit a nova entidade:


<persistence 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" version="2.0">

<!-- unidade de persistencia com o nome financas --> <persistence-unit name="financas">

<!-- Implementao do JPA, no nosso caso Hibernate --> <provider>org.hibernate.ejb.HibernatePersistence</provider>

<!-- Aqui so listadas todas as entidades --> <class>br.com.caelum.financas.modelo.Conta</class> <class>br.com.caelum.financas.modelo.Movimentacao</class>

<properties>

<!-- configuraes omitidas -->

</properties> </persistence-unit> </persistence>

Persistindo objetos envolvidos em relacionamentos


Agora que mapeamos o relacionamento, podemos utiliz-lo para armazenar as movimentaes feitas a partir de uma Conta. Para simplificar, vamos copiar a classe TesteJPA j existente e cham-la TesteJPARelacionamento. Nela j temos uma conta para associar com uma movimentao. Falta instanciar a classe Movimentacao e preencher cada valor de atributo. Primeiro a data, onde vamos usar a data atual. Ou seja, Calendar.getInstance(). Depois a descrio, pois trata-se de um pagamento de Conta de luz. O tipo da movimentao aqui TipoMovimentacao.SAIDA, classe BigDecimal. e o valor movimentado de 123.9, usando a

Movimentacao movimentacao = new Movimentacao(); movimentacao.setData(Calendar.getInstance()); movimentacao.setDescricao("Conta de luz"); movimentacao.setTipoMovimentacao(TipoMovimentacao.SAIDA); movimentacao.setValor(new BigDecimal("123.9"));

Por fim vamos associar os objetos conta e movimentacao, ou seja, chamando o mtodo setConta(..) da movimentao.
movimentacao.setConta(conta);

Com o EntityManager j em mos, podemos salvar a movimentao dentro de uma transao:


manager.getTransaction().begin(); manager.persist(movimentacao); manager.getTransaction().commit();

Segue o cdigo completo:


public class TestaRelacionamento {

public static void main(String[] args) {

Conta conta = new Conta(); conta.setTitular("Ana Maria"); conta.setBanco("Itau"); conta.setNumero("54321"); conta.setAgencia("111");

Movimentacao movimentacao = new Movimentacao(); movimentacao.setData(Calendar.getInstance()); movimentacao.setDescricao("Conta de luz"); movimentacao.setTipoMovimentacao(TipoMovimentacao.SAIDA); movimentacao.setValor(new BigDecimal("123.9"));

movimentacao.setConta(conta);

EntityManager manager = new JPAUtil().getEntityManager(); manager.getTransaction().begin();

manager.persist(movimentacao);

manager.getTransaction().commit(); manager.close(); } }

Vamos executar esse cdigo agora.

Lidando com a TransientPropertyValueException


Para nossa supresa, ser lanado uma IllegalStateException que conter como causa umaTransientPropertyValueException . O que estar errado com nosso cdigo? um problema relativamente comum de aparecer e est diretamente ligado aos estados das entidades que vimos no Captulo 3. Essa exceo indica que a nossa conta ainda est transiente e, por isso, o relacionamento no pode ser fechado no banco de dados. Podemos resolver esse problema simplesmente persistindo a Conta antes de persistir a Movimentacao. Dessa forma, bastaria adicionar manager.persist(conta):
public class TestaRelacionamento { public static void main(String[] args) { Conta conta = new Conta(); conta.setTitular("Ana Maria"); conta.setBanco("Itau"); conta.setNumero("54321"); conta.setAgencia("111"); Movimentacao movimentacao = new Movimentacao(); movimentacao.setData(Calendar.getInstance()); movimentacao.setDescricao("Conta de luz"); movimentacao.setTipoMovimentacao(TipoMovimentacao.SAIDA); movimentacao.setValor(new BigDecimal("123.9")); movimentacao.setConta(conta); EntityManager manager = new JPAUtil().getEntityManager(); manager.getTransaction().begin(); // persistindo a conta manager.persist(conta); manager.persist(movimentacao); manager.getTransaction().commit(); manager.close(); } }

Execute novamente o cdigo e veja como no recebemos mais a exceo. NOTA: No caso de querermos associar a Movimentacao a uma Conta previamente existente, bastaria atribuir um id j existente no banco de dados para uma nova Conta, e passar essa conta para a Movimentacao que ser persistida.

S-ar putea să vă placă și