- Pesquisar por algum produto baseado no nome ou na descrição
- Navegar através de uma lista de produtos classificados por categoria
- Selecionar um produto e ver seus detalhes
- Colocar o produto em um carrinho de compras
- Ver e alterar os produtos que estão no carrinho de compras
- Fazer o pedido e finalizar a compra
JPA: Modelando o negócio e criando o banco de dados
Java Persistence API (JPA) é a especificação padrão Java EE para persistencia de dados. O JPA realiza sozinho todo mapeamento a partir do modelo orientado a objetos e constrói toda base de dados relacional independente do banco dados que a aplicação vá utilizar.
O diagrama de classes abaixo nos mostra como será o modelo de negócios do projeto:
Um cliente pode realizar vários pedidos. Cada pedido é feito por apenas um cliente. Uma categoria tem vários produtos. Cada produto pertence a somente uma categoria. Um pedido pode ter vários produtos e um produto pode estar em vários pedidos.
Produtos e Pedidos representam uma relação muitos-para-muitos. Esse tipo de relação precisa ser normnalizado. Assim, criamos a classe orderProduct que contem a quantidade de itens de um pedido e o subtotal (mais sobre normalização em seguida...).
Produtos e Pedidos representam uma relação muitos-para-muitos. Esse tipo de relação precisa ser normnalizado. Assim, criamos a classe orderProduct que contem a quantidade de itens de um pedido e o subtotal (mais sobre normalização em seguida...).
Codificando o modelo (para clareza, as declarações import foram omitidas)
Abra a IDE NetBeans, crie um novo projeto Java Web, dê o nome de StarkHouseECommerce e finalize. Delete o arquivo index.html que o NetBeans cria automaticamente.
Para utilizar o JPA você precisa ter as seguintes biblioteca no seu classpath, conforme a imagem da janela de projetos do NetBeans:
Você pode baixar as bibliotecas aqui hibernate 4.3.5.Final (todos os arquivos na pasta /lib/required). Também deve usar esta hibernate-entitymanager. E o driver do banco de dados PostgreSQL.
A especificação do JPA nos diz que precisamos ter o arquivo persistence.xml no projeto. É nele que ficam as informações de acesso ao banco de dados. No nosso exemplo, o arquivo deve ser como segue:
Criando as Entidades
Classe EClient.java, a entidade que realiza as compras no nosso site.
De acordo com o nosso digrama de classes, Product e EOrder têm entre si uma relação N para N, isto é, muitos-para-muitos. Esse tipo de relação só existe conceitualmente, na hora de implementar precisamos normaliza-la, tranformando-a em 2 relações 1 para N, uma-para-muitos. Dessa forma, criamos uma classe extra para armazenar a quantidade de produtos de cada pedido, bem como o subtotal (o cliente pode ter ganho um desconto no dia do pedido, mas o preço real do produto continua inalterado na base de dados, por exemplo). Criamos a classe OrderProduct, a qual possui uma referência tanto para Product quanto para EOrder, mais os campos quantity e total.
De acordo com a especificação do JPA, o ID dessa nova entidade deve ficar em uma classe separada, vamos chamá-la de OrderProductId:
Agora que temos todo o modelo pronto, é hora de popular as tabelas do banco de dados. Não se esqueça de criar um banco de dados chamado ecommerce. O JPA criará todas as tabelas e os relacionamentos para você.
Para preencher as tabelas crie uma classe chamada teste com um método principal e execute-a:
O JPA nos auxilia na construção do modelo e no relacionamento com o banco de dados.
O próximo passo na parte 2 deste artigo é criar a interface com o usuário para que ele possa se cadastrar e comprar os produtos registrados em nosso banco de dados. Para nos auxiliar nesse tarefa utilizaremos os frameworks Servlets e Java Server Pages (JSP)!
Você pode baixar as bibliotecas aqui hibernate 4.3.5.Final (todos os arquivos na pasta /lib/required). Também deve usar esta hibernate-entitymanager. E o driver do banco de dados PostgreSQL.
A especificação do JPA nos diz que precisamos ter o arquivo persistence.xml no projeto. É nele que ficam as informações de acesso ao banco de dados. No nosso exemplo, o arquivo deve ser como segue:
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"> <persistence-unit name="ecommerce" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <properties> <property name="javax.persistence.jdbc.url" value="jdbc:postgresql://localhost:5432/ecommerce"/> <property name="javax.persistence.jdbc.user" value="postgres"/> <property name="javax.persistence.jdbc.password" value="postgres"/> <property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver"/> <property name="hibernate.show_sql" value="true"/> <property name="hibernate.format_sql" value="true"/> <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/> <property name="hibernate.hbm2ddl.auto" value="update"/> </properties> </persistence-unit> </persistence>No meu banco, usuário e senha são ambos postgres. E a porta geralmente é 5432. Se no seu caso for diferente, apenas faça as adequações. Crie um banco de dados chamado ecommerce.
Criando as Entidades
Classe EClient.java, a entidade que realiza as compras no nosso site.
//imports omitidos
@Entity
@Table(name = "eclient")
public class EClient implements Serializable{
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; //chave primária gerada sequencialmente
@Column
private String firstName;
@Column
private String lastName;
@Column @Temporal(TemporalType.TIMESTAMP)
private Date birthDate; //campo tipo data e tempo
@Column
private String creditCard;
@Column
private String email;
@Column
private String login;
//esta anotação indica uma relação "um-pra-muitos" entre cliente e pedido
@OneToMany(mappedBy = "client")
private List<EOrder> orders;
//construtor
public EClient() {
orders = new ArrayList<>();
}
//getters & setters para cada atributo
}
A classe EOrder que representa os pedidos do nosso sistema:
@Entity
public class EOrder {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column
@Temporal(TemporalType.TIMESTAMP)
private Date date;
@ManyToOne //cada pedido pertence a um cliente
@JoinColumn(name = "CLI_ID") //equivale a chave estrangeira da classe EClient
private EClient client;
@OneToMany(mappedBy = "eorder") //um pedido tem muitos produtos
private List<OrderProduct> orderProduct;
public EOrder() {
client = new EClient();
orderProduct = new ArrayList<>();
}
//getters e setters omitidos
}
A classe Product:@Entity
@Table(name = "product")
public class Product {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column
private String name;
@Column
private Double price;
@Column
private String description;
@ManyToOne //cada produto pertence a uma categoria
@JoinColumn(name = "CAT_ID", nullable = false) //chave estrangeira de Category
private Category category;
@OneToMany(mappedBy = "product") //um produto está em muitos pedidos
private List<OrderProduct> orderProduct;
public Product() {
category = new Category();
orderProduct = new ArrayList<>();
}
//getters e setters omitidos
}
Normalizando a relação Produto e PedidoDe acordo com o nosso digrama de classes, Product e EOrder têm entre si uma relação N para N, isto é, muitos-para-muitos. Esse tipo de relação só existe conceitualmente, na hora de implementar precisamos normaliza-la, tranformando-a em 2 relações 1 para N, uma-para-muitos. Dessa forma, criamos uma classe extra para armazenar a quantidade de produtos de cada pedido, bem como o subtotal (o cliente pode ter ganho um desconto no dia do pedido, mas o preço real do produto continua inalterado na base de dados, por exemplo). Criamos a classe OrderProduct, a qual possui uma referência tanto para Product quanto para EOrder, mais os campos quantity e total.
De acordo com a especificação do JPA, o ID dessa nova entidade deve ficar em uma classe separada, vamos chamá-la de OrderProductId:
@Entity
@IdClass(OrderProductId.class) //indica a classeId de OrderProduct
public class OrderProduct {
@Id
@ManyToOne
@JoinColumn(name = "prd_id")
Product product;
@Id
@ManyToOne
@JoinColumn(name = "ord_id")
EOrder eorder;
@Column
private Integer quantity; //a quantidade de produtos no pedido
@Column //valor total deste produto no pedido, geralmente preço x quantidade
private Double total;
//getters e setters omitidos
}
A classe OrderProductId:public class OrderProductId implements Serializable{
int eorder;
int product;
//getters e setters omitidos
//é obrigatório a implementação dos métodos hashCode() e equals() utilizando os dois campos
}
A classe Category:@Entity
@Table(name = "category")
public class Category {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column
private String name;
@OneToMany(mappedBy = "category", fetch = FetchType.LAZY)
private List<Product> products; //uma categoria tem muitos produtos
public Category() {
products = new ArrayList<>();
}
//getters e setters omitidos
}
Populando o banco de dadosAgora que temos todo o modelo pronto, é hora de popular as tabelas do banco de dados. Não se esqueça de criar um banco de dados chamado ecommerce. O JPA criará todas as tabelas e os relacionamentos para você.
Para preencher as tabelas crie uma classe chamada teste com um método principal e execute-a:
public class teste {
public static void main(String[] args) {
//"ecommerce" é o nome da unidade de persistencia conforme definido no arquivo persistence.xml
EntityManagerFactory emf = Persistence.createEntityManagerFactory("ecommerce");
EntityManager em = emf.createEntityManager();
//criando as categorias
Category eletronicos = new Category("eletrônicos", null);
Category suplementos = new Category("suplementos", null);
Category livros = new Category("livros", null);
//criando os produtos e passando a respectiva categoria no construtor
Product ps4 = new Product("PS4", 566.23,
"Adquira o PS4™ e prepare-se para a experiência de jogo mais imersiva possível!", eletronicos);
Product noteDell = new Product("NoteBook Dell", 303.99, "Linux, 15.6, 8GB, i7", eletronicos);
Product IPhone = new Product("IPhone 5S", 299.99, "16GB, 4G, Explore o mundo do iPhone!", eletronicos);
Product wheyProt = new Product("Whey Protein ON", 32.01, "Whey Protein Isolada ON. Rápida absorção", suplementos);
Product multiAz = new Product("Multi AZ Final", 11.0, "Multi AZ para homens e mulheres", suplementos);
Product omega3 = new Product("Omega 3", 65.99, "Puro Omega 3 importado 120 caps", suplementos);
Product javaHowTo = new Product("Java como Programar", 80.15, "Java como Programar, Deitel, Deitel, 1100 páginas", livros);
Product jsf = new Product("Core JSF", 80.15, "Core JSF, Geary Horstmann, 400 páginas", livros);
Product cronicasGeloFogo = new Product("Crônicas de Gelo e Fogo", 55.88, "O Festim dos Corvos, RR Martin, 800 páginas", livros);
//antes de salvar as categorias e os produtos, precisamos abrir uma transação
em.getTransaction().begin();
//persist() é o método de EntityManger para persistir os objetos no banco
em.persist(eletronicos);
em.persist(suplementos);
em.persist(livros);
em.persist(ps4);
em.persist(noteDell);
em.persist(IPhone);
em.persist(wheyProt);
em.persist(multiAz);
em.persist(omega3);
em.persist(javaHowTo);
em.persist(jsf);
em.persist(cronicasGeloFogo);
//para finalizar confirme a transação e feche os recursos utilizados
em.getTransaction().commit();
emf.close();
}
}
Repare como ficou nossa janela de projetos no NetBans. Repare também que no console da IDE o JPA exibe as declarações sql que foram geradas no banco:O JPA nos auxilia na construção do modelo e no relacionamento com o banco de dados.
O próximo passo na parte 2 deste artigo é criar a interface com o usuário para que ele possa se cadastrar e comprar os produtos registrados em nosso banco de dados. Para nos auxiliar nesse tarefa utilizaremos os frameworks Servlets e Java Server Pages (JSP)!





