By GokiSoft.com| 10:45 26/12/2020|
Spring MVC

[Share Code] Bài tập - Quản lý sản phẩm - Lập trình Spring MVC



B1. Thiết kế database

create table product (
	id int primary key auto_increment,
	title varchar(200) not null,
	content longtext,
	thumbnail varchar(500),
	price float,
	discount float,
	created_at datetime,
	updated_at datetime
)

B2. Tao project
- Sua config
- Ket noi vs CSDL
	- Tai thu vien jdbc mysql driver => copy vao project
	- Add thu vien trong project
	- Generate database (ORM)
	- Sua lai file cau hinh Persistence
- Product
	- Hien thi danh sach san pham => /product/index




#persistence.xml


<?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="BT1994PU" transaction-type="RESOURCE_LOCAL">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <class>com.entity.Product</class>
    <properties>
      <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/product_mgr?serverTimezone=UTC"/>
      <property name="javax.persistence.jdbc.user" value="root"/>
      <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
      <property name="javax.persistence.jdbc.password" value=""/>
    </properties>
  </persistence-unit>
</persistence>


#ProductController.java


/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.controller;

import com.entity.Product;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

/**
 *
 * @author teacher
 */
@Controller
@RequestMapping(value = "/product")
public class ProductController {
    @RequestMapping(value = "/index", method = RequestMethod.GET)
    public String index(@RequestParam Map<String, String> form, ModelMap modelMap) {
        //Lay du lieu database
        //B1. Ket noi toi CSDL
        EntityManagerFactory factory = Persistence.createEntityManagerFactory("BT1994PU");
        EntityManager em = factory.createEntityManager();
        
        //B2. Tao query toi database
        Query q = null;
        if(form.containsKey("s")) {
            String s = form.get("s");
            
            q = em.createNamedQuery("Product.findByTitleLike", Product.class);
            q.setParameter("title", "%"+s+"%");
        } else {
            q = em.createNamedQuery("Product.findAll", Product.class);
        }
        
        //B3. Lay du lieu
        List<Product> list = q.getResultList();
        
        modelMap.put("productList", list);
        
        return "/product/index";
    }
    
    @RequestMapping(value = "/view", method = RequestMethod.GET)
    public String view(@RequestParam Map<String, String> form, ModelMap modelMap) {
        Product product = new Product();
        
        if(form.containsKey("id")) {
            int id = Integer.parseInt(form.get("id"));
            //B1. Ket noi toi CSDL
            EntityManagerFactory factory = Persistence.createEntityManagerFactory("BT1994PU");
            EntityManager em = factory.createEntityManager();
            
            product = em.find(Product.class, id);
            
            if(product == null) {
                product = new Product();
            }
        }
        
        modelMap.put("product", product);
        
        return "/product/view";
    }
    
    @RequestMapping(value = "/save", method = RequestMethod.POST)
    public String save(@RequestParam Map<String, String> form) {
        String title = form.get("title");
        String thumbnail = form.get("thumbnail");
        String content = form.get("content");
        float price = Float.parseFloat(form.get("price"));
        float discount = Float.parseFloat(form.get("discount"));
        
        int id = 0;
        if(form.containsKey("id") && !form.get("id").isEmpty()) {
            id = Integer.parseInt(form.get("id"));
        }
        
        //B1. Ket noi toi CSDL
        EntityManagerFactory factory = Persistence.createEntityManagerFactory("BT1994PU");
        EntityManager em = factory.createEntityManager();
        
        if(id > 0) {
            //update
            Product productFind = em.find(Product.class, id);
            
            em.getTransaction().begin();
        
            productFind.setTitle(title);
            productFind.setThumbnail(thumbnail);
            productFind.setContent(content);
            productFind.setPrice(price);
            productFind.setDiscount(discount);
            productFind.setUpdatedAt(new Date());

            em.getTransaction().commit();
        } else {
            //insert
            em.getTransaction().begin();
        
            Product product = new Product();
            product.setTitle(title);
            product.setThumbnail(thumbnail);
            product.setContent(content);
            product.setPrice(price);
            product.setDiscount(discount);
            product.setCreatedAt(new Date());
            product.setUpdatedAt(new Date());

            em.persist(product);

            em.getTransaction().commit();
        }
        
        return "redirect:index.html";
    }
    
    @RequestMapping(value = "/delete", method = RequestMethod.POST)
    public String delete(@RequestParam Map<String, String> form) {
        int id = 0;
        if(form.containsKey("id") && !form.get("id").isEmpty()) {
            id = Integer.parseInt(form.get("id"));
        }
        
        //B1. Ket noi toi CSDL
        EntityManagerFactory factory = Persistence.createEntityManagerFactory("BT1994PU");
        EntityManager em = factory.createEntityManager();
        
        if(id > 0) {
            //delete
            Product productFind = em.find(Product.class, id);
            
            if(productFind != null) {
                em.getTransaction().begin();
                em.remove(productFind);
                em.getTransaction().commit();
            }
        }
        return "redirect:index.html";
    }
    
    //delete/1.html
    @RequestMapping(value = "/delete/{id}", method = RequestMethod.POST)
    public String delete2(@PathVariable int id) {
        //B1. Ket noi toi CSDL
        EntityManagerFactory factory = Persistence.createEntityManagerFactory("BT1994PU");
        EntityManager em = factory.createEntityManager();
        
        if(id > 0) {
            //delete
            Product productFind = em.find(Product.class, id);
            
            if(productFind != null) {
                em.getTransaction().begin();
                em.remove(productFind);
                em.getTransaction().commit();
            }
        }
        return "redirect:index.html";
    }
}


#Product.java


/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.entity;

import java.io.Serializable;
import java.util.Date;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.xml.bind.annotation.XmlRootElement;

/**
 *
 * @author teacher
 */
@Entity
@Table(name = "product")
@XmlRootElement
@NamedQueries({
    @NamedQuery(name = "Product.findAll", query = "SELECT p FROM Product p")
    , @NamedQuery(name = "Product.findById", query = "SELECT p FROM Product p WHERE p.id = :id")
    , @NamedQuery(name = "Product.findByTitle", query = "SELECT p FROM Product p WHERE p.title = :title")
    , @NamedQuery(name = "Product.findByTitleLike", query = "SELECT p FROM Product p WHERE p.title like :title")
    , @NamedQuery(name = "Product.findByThumbnail", query = "SELECT p FROM Product p WHERE p.thumbnail = :thumbnail")
    , @NamedQuery(name = "Product.findByPrice", query = "SELECT p FROM Product p WHERE p.price = :price")
    , @NamedQuery(name = "Product.findByDiscount", query = "SELECT p FROM Product p WHERE p.discount = :discount")
    , @NamedQuery(name = "Product.findByCreatedAt", query = "SELECT p FROM Product p WHERE p.createdAt = :createdAt")
    , @NamedQuery(name = "Product.findByUpdatedAt", query = "SELECT p FROM Product p WHERE p.updatedAt = :updatedAt")})
public class Product implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "id")
    private Integer id;
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 200)
    @Column(name = "title")
    private String title;
    @Lob
    @Size(max = 2147483647)
    @Column(name = "content")
    private String content;
    @Size(max = 500)
    @Column(name = "thumbnail")
    private String thumbnail;
    // @Max(value=?)  @Min(value=?)//if you know range of your decimal fields consider using these annotations to enforce field validation
    @Column(name = "price")
    private Float price;
    @Column(name = "discount")
    private Float discount;
    @Column(name = "created_at")
    @Temporal(TemporalType.TIMESTAMP)
    private Date createdAt;
    @Column(name = "updated_at")
    @Temporal(TemporalType.TIMESTAMP)
    private Date updatedAt;

    public Product() {
    }

    public Product(Integer id) {
        this.id = id;
    }

    public Product(Integer id, String title) {
        this.id = id;
        this.title = title;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public String getThumbnail() {
        return thumbnail;
    }

    public void setThumbnail(String thumbnail) {
        this.thumbnail = thumbnail;
    }

    public Float getPrice() {
        return price;
    }

    public void setPrice(Float price) {
        this.price = price;
    }

    public Float getDiscount() {
        return discount;
    }

    public void setDiscount(Float discount) {
        this.discount = discount;
    }

    public Date getCreatedAt() {
        return createdAt;
    }

    public void setCreatedAt(Date createdAt) {
        this.createdAt = createdAt;
    }

    public Date getUpdatedAt() {
        return updatedAt;
    }

    public void setUpdatedAt(Date updatedAt) {
        this.updatedAt = updatedAt;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Product)) {
            return false;
        }
        Product other = (Product) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "com.entity.Product[ id=" + id + " ]";
    }
    
}


#dispatcher-servlet.xml


<?xml version='1.0' encoding='UTF-8' ?>
<!-- was: <?xml version="1.0" encoding="UTF-8"?> -->
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
       http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc">

    <bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"/>
    <mvc:annotation-driven></mvc:annotation-driven>
    <context:component-scan base-package="com.controller"/>

    <!--
    Most controllers will use the ControllerClassNameHandlerMapping above, but
    for the index controller we are using ParameterizableViewController, so we must
    define an explicit mapping for it.
    -->
    <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="index.html">indexController</prop>
            </props>
        </property>
    </bean>

    <bean id="viewResolver"
          class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          p:prefix="/WEB-INF/view/"
          p:suffix=".jsp" />

    <!--
    The index controller.
    -->
    <bean name="indexController"
          class="org.springframework.web.servlet.mvc.ParameterizableViewController"
          p:viewName="index" />

</beans>


#index.jsp


<%-- 
    Document   : index
    Created on : Dec 26, 2020, 8:51:24 AM
    Author     : teacher
--%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
	<title>Product List - Page</title>
	<!-- Latest compiled and minified CSS -->
	<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"/>

	<!-- jQuery library -->
	<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

	<!-- Popper JS -->
	<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>

	<!-- Latest compiled JavaScript -->
	<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"></script>
</head>
<body>
	<div class="container">
		<div class="panel panel-primary">
			<div class="panel-heading">
				<h1 style="text-transform: uppercase">Product List - Page</h1>
			</div>
			<div class="panel-body">
                                <a href="view.html"><button class="btn btn-success" style="margin-bottom: 15px;">Add Product</button></a>
                                <form method="get" action="index.html" style="float: right">
                                    <input type="text" class="form-control" name="s" style="width: 200px; float: right" placeholder="Tim kiem ..."/>
                                </form>
				<table class="table table-bordered table-hovered">
					<thead>
						<tr>
							<th>STT</th>
							<th>Thumbnail</th>
							<th>Title</th>
							<th>Price</th>
							<th>Discount</th>
							<th>Updated At</th>
                                                        <th></th>
                                                        <th></th>
						</tr>
					</thead>
					<tbody>
                                            <c:forEach items="${productList}" var="item" varStatus="loop">
						<tr>
							<td>${loop.index + 1}</td>
                                                        <td>
                                                            <img src="${item.thumbnail}" width="80px">
                                                        </td>
							<td>${item.title}</td>
							<td>${item.price}</td>
							<td>${item.discount}</td>
							<td>${item.updatedAt}</td>
                                                        <td>
                                                            <a href="view.html?id=${item.id}"><button class="btn btn-warning">Edit</button></a>
                                                        </td>
                                                        <td>
                                                            <button class="btn btn-danger" onclick="deleteProduct(${item.id})">Delete</button>
                                                        </td>
						</tr>
                                            </c:forEach>
					</tbody>
				</table>
			</div>
		</div>
	</div>
    
    <script>
        function deleteProduct(id) {
            var option = confirm('Ban co chac chan muon xoa du lieu nay khong???')
            if(!option) return
            
            $.post('delete.html', {
                'id': id
            }, function(data) {
                location.reload()
            })
//            $.post("delete/"+id+".html", {}, function(data) {
//                location.reload()
//            })
        }
    </script>
</body>
</html>


#view.jsp


<%-- 
    Document   : view
    Created on : Dec 26, 2020, 9:41:14 AM
    Author     : teacher
--%>

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
	<title>Product Editor - Page</title>
	<!-- Latest compiled and minified CSS -->
	<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"/>

	<!-- jQuery library -->
	<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

	<!-- Popper JS -->
	<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>

	<!-- Latest compiled JavaScript -->
	<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"></script>
</head>
<body>
	<div class="container">
		<div class="panel panel-primary">
			<div class="panel-heading">
				<h2 class="text-center">Product Editor - Page</h2>
			</div>
			<div class="panel-body">
                            <form method="post" action="save.html">
				<div class="form-group">
				  <label for="usr">Title:</label>
                                  <input type="text" name="id" value="${product.id}" hidden="true"/>
                                  <input required="true" type="text" class="form-control" id="title" name="title" value="${product.title}"/>
				</div>
				<div class="form-group">
				  <label for="email">Thumbnail:</label>
                                  <input required="true" type="text" class="form-control" id="thumbnail" name="thumbnail" value="${product.thumbnail}"/>
				</div>
				<div class="form-group">
				  <label for="birthday">Price:</label>
                                  <input type="number" class="form-control" id="price" name="price" value="${product.price}"/>
				</div>
				<div class="form-group">
				  <label for="pwd">Discount:</label>
                                  <input required="true" type="number" class="form-control" id="discount" name="discount" value="${product.discount}"/>
				</div>
				<div class="form-group">
				  <label for="address">Description:</label>
                                  <textarea class="form-control" rows="5" name="content">${product.content}</textarea>
				</div>
				<button class="btn btn-success">Save</button>
                            </form>
			</div>
		</div>
	</div>
</body>
</html>


Phản hồi từ học viên

5

(Dựa trên đánh giá ngày hôm nay)