Ola PessoAll!
Dando continuidade a temática de Persistência de dados, demonstrarei neste post, a implementação do relacionamento de cardinalidade 1:N (1 para N), o que implica o uso das annotations: @ManyToOne e @OneToMany.
Como já visto em posts anteriores, o uso de frameworks ORM agregam bastante facilidade e agilidade no desenvolvimento de aplicações; sabe-se que modelagens de dados propiciam a coexistência de sua estrutura, ou seja, priorizam (na maioria das vezes) o uso de relacionamentos, ou seja, objetos de banco não têm muita significância quando isolados.
Para a obtenção de informações coesas, bem como, significantes ao contexto de negócio, o uso de relacionamentos é imprescindível, desta forma, saber manipular os relacionamentos no contexto ORM é significativamente importante.
Segundo a documentação da especificação JEE 6 (http://docs.oracle.com/javaee/6/tutorial/doc/bnbqa.html#bnbqh), tem-se:
- One-to-many: An entity instance can be related to multiple instances of the other entities. A sales order, for example, can have multiple line items. In the order application, Order would have a one-to-many relationship with LineItem. One-to-many relationships use the javax.persistence.OneToMany annotation on the corresponding persistent property or field.
- Many-to-one: Multiple instances of an entity can be related to a single instance of the other entity. This multiplicity is the opposite of a one-to-many relationship. In the example just mentioned, the relationship to Order from the perspective ofLineItem is many-to-one. Many-to-one relationships use the javax.persistence.ManyToOne annotation on the corresponding persistent property or field.
Será utilizado o projeto Persistência constituídos nos posts anteriores para a implementação. Ao trabalho!
A MODELAGEM
No nosso banco de dados que abrigava o cadastro de produtos, criaremos a tabela Categoria e o devido relacionamento com produto, conforme modelagem:
O script para a criação da tabela Categoria e inclusão do relacionamento em Produto, segue:
create table categoria ( id_categoria serial, nome varchar(45) not null, descricao varchar(200), fg_ativo boolean, primary key (id_categoria)); alter table produto add column id_categoria integer; alter table produto add constraint categoria_id_categoria_fk foreign key (id_categoria) references categoria (id_categoria);
IMPLEMENTAÇÃO
Feitas as alterações procederemos ao mapeamento, que deverá ser constituído da seguinte forma:
Produto:
package br.com.serjava.persistencia.entity; //imports omitidos @Entity @Table(name="produto") @SequenceGenerator(name="produto_id_produto_seq", sequenceName="produto_id_produto_seq", allocationSize=1) public class Produto implements Serializable { private static final long serialVersionUID = -8121617132071401241L; @Id @GeneratedValue(generator="produto_id_produto_seq", strategy=GenerationType.SEQUENCE) @Column(name="id_produto") private Integer idProduto; @Column(name="nm_produto") private String nomeProduto; @Column(name="quantidade") private Integer quantidade; @Column(name="valor") private Double valor; //relacionamento com categoria @ManyToOne @JoinColumn(name="id_categoria", referencedColumnName="id_categoria") private Categoria category; //getters and setters
Categoria:
package br.com.serjava.persistencia.entity; //imports omitidos @Entity @Table(name="categoria") @SequenceGenerator(name="categoria_id_categoria_seq", sequenceName="categoria_id_categoria_seq", allocationSize=1) public class Categoria implements Serializable { private static final long serialVersionUID = -8765631845563878481L; @Id @GeneratedValue(generator="categoria_id_categoria_seq", strategy=GenerationType.SEQUENCE) @Column(name="id_categoria") private Long idCategoria; @Column(name="nome", nullable=false) private String nome; @Column(name="descricao") private String descricao; @Column(name="fg_ativo") private Boolean ativo; @OneToMany(mappedBy="categoria") private List<Produto> listaProdutos; //getters and setters
Observe que na entidade Produto temos um objeto de Categoria, pois, de acordo com o modelo elaborado, um produto tem uma categoria; já na entidade Categoria, note a existência de uma lista de Produtos, o que indica que uma categoria pode estar associada a N produtos.
Atenção! O atributo mappedBy presente na annotation @OneToMany, presente na entidade Categoria, deve conter a nomenclatura dada ao objeto que referencia-se a uma categoria na entidade Produto!
Na entidade Produto, temos a anotação @JoinColumn (você deve estar pensando: Nossa é aqui que o join é feito? SIM!), seus atributos name e referencedColumnName significam, respectivamente, o nome do atributo correspondente a foreign key de categoria na tabela produto (no banco de dados) e o nome da primary key representativa da tabela Categoria!
O próximo passo é a criação do objeto de acesso a dados (DAO) para a entidade Categoria. Felizmente nosso projeto está usando a arquitetura DAO Genérico, o que nos poupará bastante trabalho. A criação de CategoriaDAO e CategoriaDAOImpl deverá ser feita de forma análoga a Produto, para não ser repetitivo, verifique nos posts anteriores (em caso de dúvidas consulte: Persistência - DAO Genérico).
Para efetivarmos o relacionamento, criaremos 2 Produtos e os vincularemos a uma dada Categoria, na classe main:
public static void main(String... args) { ProdutoDAO produtoDAO = new ProdutoDAOImpl(); CategoriaDAO categoriaDAO = new CategoriaDAOImpl(); Categoria categoria = new Categoria(); categoria.setNome("Livros Informática"); categoria.setDescricao("Livros de desenvolvimento, banco de dados..."); categoria.setAtivo(true); //Categoria é salva no banco e recuperada - uso do merge, ou seja, tem-se o objeto categoria // sincronizado no contexto de persistência categoria = categoriaDAO.save(categoria); Produto produto = new Produto(); produto.setNomeProduto("Head First - Java"); produto.setQuantidade(11); produto.setValor(99.99); //atribui a cateogira Livros Informática ao produto produto.setCategoria(categoria); Produto produto2 = new Produto(); produto2.setNomeProduto("Head First - Servlets and JSP"); produto2.setQuantidade(55); produto2.setValor(128.99); //atribui a cateogira Livros Informática ao produto produto2.setCategoria(categoria); //salva-se os produtos produtoDAO.save(produto); produtoDAO.save(produto2); List<Produto> listaProdutosCadastrados = produtoDAO.getAll(Produto.class); for (Produto p : listaProdutosCadastrados) { System.out.println(p.getNomeProduto()); } }
O resultado esperado é a inserção de 2 produtos vínculados a categoria criada. Vejamos o resultado no banco:
Observe que foi criada a Categoria 3 - Livros Informática, e os produtos 22 e 23, vinculados a esta categoria, pelo código 3!
Espero que tenham gostado!