Spring boot + mybatis + spring technology integration to realize CRUD operation of commodity brand module

Business description

Requirement description

There is a commodity subsystem in any e-commerce system, and there will be a brand information management associated with commodities. In the current business system design, we want to design and implement the management of commodity brand information

Business architecture analysis

In brand information management, it is necessary to add, modify, query and delete commodity brand information, as shown in the figure:

Basic business prototype design

Based on the brand business description, analyze and design the business prototype of the brand module, as shown in the figure:

  • Brand list page

  • Brand editing page

Analysis and design of project technical framework

In the implementation process of brand management module, we use typical C/S architecture The client is implemented based on the browser, the server uses tomcat, and the database uses MySQL The specific application layer is implemented based on MVC layered architecture

Application analysis and selection of project technology stack

  • Client technology: html,css,javascript,bootstrap
  • Server side technologies: hikaricp,mybatis,spring,springboot,thymeleaf
  • Database technology: mysql,sql
  • Development toolset: jdk1 8,maven3. 6.3´╝îidea2020. two

Analysis and design of core API of project brand module

Based on the layered architecture design idea, the brand API is designed, as shown in the figure:

Analysis and design of database and table

Design and create database

If the database already exists, delete the database first. The code is as follows:

drop database if exists dbbrand;

Create a new database with the following code:

create database dbbrand default character set utf8;

Design and create brand table

Open the database with the following statement:

use dbbrand;

Create brand table in dbbrand database

create table tb_brand(
     id bigint primary key auto_increment,
     name varchar(100) not null,
     remark text,
     createdTime datetime not null
)engine=InnoDB;

Perform database initialization based on SQL script

Write the database design script to brand SQL, and then execute as follows:

Open the built-in client of mysql and log in to mysql. The instructions are as follows:

mysql -uroot -proot

Set the client code. The instructions are as follows:

set names utf8;

Execute the sql script with the following instructions:

source d:/brand.sql

After the script is executed successfully, execute the following statement before the client queries the data:

set names gbk;

Project environment initialization

Prepare for operation

1)JDK 1.8
2)Maven 3.6.3
3)IDEA 2020.2
4)MySQL 5.7+

Create project Module

Open idea, and then create a project module based on the design, as shown in the figure:

Add project Module dependency

  • MySQL driver
<dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <scope>runtime</scope>
</dependency>
  • Srping Jdbc provides HikariCP connection pool
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
  • MyBatis resources
<dependency>
   <groupId>org.mybatis.spring.boot</groupId>
   <artifactId>mybatis-spring-boot-starter</artifactId>
   <version>2.1.3</version>
</dependency>
  • Spring Web dependency (with a built-in tomcat service)
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
</dependency>
  • Thymeleaf dependency (html template engine)
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

Basic configuration of project Module

Open the project Module configuration file application Properties and add the following:

#spring server

server.port=80

# spring datasource
spring.datasource.url=jdbc:mysql:///dbbrand?serverTimezone=GMT%2B8&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=root

# spring mybatis

mybatis.mapper-locations=classpath:/mapper/*/*.xml

# spring log

logging.level.com.cy=debug

#spring thymeleaf
spring.thymeleaf.cache=false
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html

Start the project for preliminary environmental test and analysis

  • Port number occupied

  • Database connection error

Query and presentation of brand data

Business description

Query the brand information in the database, and then present it on the client based on html technology, as shown in the figure:

Design of service end brand query timing

Design the access timing based on the query request, as shown in the figure:

Design and implementation of domain object (POJO)

Set the Brand object to encapsulate the Brand information queried from the database based on this object. The code is as follows:

package com.cy.pj.brand.pojo;
import java.util.Date;
public class Brand {
    private Integer id;
    private String name;
    private String remark;
    private Date createdTime;
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getRemark() {
        return remark;
    }
    public void setRemark(String remark) {
        this.remark = remark;
    }
    public Date getCreatedTime() {
        return createdTime;
    }
    public void setCreatedTime(Date createdTime) {
        this.createdTime = createdTime;
    }
    @Override
    public String toString() {
        return "Brand{" +
                "id=" + id +
                ", name='" + name + ''' +
                ", remark='" + remark + ''' +
                ", createdTime=" + createdTime +
                '}';
    }
}

Design and implementation of data logical object (DAO) query method

Design data access objects and methods for accessing Brand data. The key steps are as follows:

Step 1: define BrandDao interface. The code is as follows:

package com.cy.pj.brand.dao;
@Mapper
public interface BrandDao{

}

Step 2: define the brand query method in BrandDao. The code is as follows:

List<Brand> findBrands(String name);

Step 3: define SQL mapping based on query method
Create the mapper/brand directory in the resources directory and add brandmapper XML file. The key codes are as follows:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cy.pj.brand.dao.BrandDao">
    <select id="findBrands" resultType="com.cy.pj.brand.pojo.Brand">
        select id,name,remark,createdTime
        from tb_brand
        <if test="name!=null and name!=''">
            where name like concat("%",#{name},"%")
        </if>
    </select>
</mapper>

Where: concat is the string connection function provided in mysql

Step 4: unit test the query method of the data layer. The code is as follows:

package com.cy.pj.brand.dao;
@SpringBootTests
public class BrandDaoTests{
     @Autowired
     private BrandDao brandDao;
     @Test
     void testFindBrands(){
        List<Brand> list=brandDao.findBrands("TCL");
        for(Brand b:list){
           System.out.println(b);
        }
     }
} 

Step 5: BUG analysis during testing?

  • BindingException, as shown in the figure:

  • ExecutorException, as shown in the figure:

Design and implementation of business logic object (Service) query method

The business logic object is responsible for the specific business processing of the module, such as parameter verification, transaction control, permission control, logging, etc

Step 1: define business interface

package com.cy.pj.brand.service;
public interface BrandService{
} 

Step 2: add brand query method in BrandService interface

List<Brand> findBrands(String name);

Step 3: define the BrandService interface implementation class BrandServiceImpl

package com.cy.pj.brand.service.impl;

@Service
public class BrandServiceImpl implements BrandService{
     private static final Logger log=
     LoggerFactory.getLogger(BrandServiceImpl.class);
     
     @Autowired
     private BrandDao brandDao;
     public List<Brand> findBrands(String name){
            long t1=System.currentTimeMillis();
            List<Brand> list=brandDao.findBrands(name);
            long t2=System.currentTimeMillis();
            log.info("findBrands->time->{}",(t2-t1));
            return list;
     }
} 

Step 3: define the unit test class of BrandService interface method and test and analyze the business

package com.cy.pj.brand.service;
@SpringBootTest
public class BrandServiceTests{
    @Autowired
    private BrandService brandService;
    @Test
    void testFindBrands(){
        List<Brand> list=brandService.findBrands();
        for(Brand b:list){
            System.out.println(b);
        }
    }
}

Step 4: Bug analysis during testing

  • NoSuchBeanDefinition, as shown in the figure:

  • NullPointerException, as shown in the figure:

Design and implementation of control logic object (Controller) query method

In the control logic object, it is mainly responsible for the logical control of request and response, such as request url mapping, parameter mapping, request mode, result set encapsulation, parsing, response design, etc

Step 1: define the Controller class

package com.cy.pj.brand.controller;
@Controller
public class BrandController{
   @Autowired
   private BrandService brandService;
}

Step 2: add a method to process query requests in the Controller

@GetMapping(value={"/brand/doFindBrands/{name}","/brand/doFindBrands"})
public String doFindBrands(@PathVariable(required = false) String name, Model model){
    List<Brand> list=brandService.findBrands(name);
    model.addAttribute("list", list);
    return "brand/brand";//The first brand is the directory and the second brand is view name
} 

Among them,
1) When @ getmapping describes a method, it means that this method can only process Get requests. The value attribute inside the annotation can specify multiple URLs
2)@PathVariable is used to describe method parameters. It means that the value of method parameters can come from the variable value inside {} in the url. required=false means that parameters can not pass values

Design and implementation of client brand list page

Create a brand directory under the templates directory of the project and add brand The key codes of the HTML page are as follows:

<table>
    <thead>
      <tr>
        <th>id</th>
        <th>name</th>
        <th>createdTime</th>
      </tr>
    </thead>
    <tbody>
      <tr th:each="brand: ${list}">
         <td th:text="${brand.id}">10</td>
         <td th:text="${brand.name}">AAA</td>
         <td th:text="${#dates.format(brand.createdTime, 'yyyy/MM/dd  
         HH:mm')}">2020/10/11</td>
       </tr>
 </tbody>
</table>

Of which:
1) ${} is the EL expression in thymeleaf, which is used to obtain data from the server model
2)th:each is a custom tag attribute defined for thymeleaf, which is used to iterate data
3)th:text is a custom label attribute defined for thymeleaf, which is used to set the text content

Start the service for access test and analyze the results

Start the service, open the browser, enter the specified url and access it. The data presentation process is shown in the figure:

Bug analysis and solutions during startup and operation

  • Page element parsing exception, as shown in the figure:

  • The template page cannot be found, as shown in the figure:

Analysis and implementation of brand module deletion business

Business description

On the brand list page, click the delete button behind the record of the current line to delete the brand based on the record id of the current line. After the deletion is successful, refresh the page As shown in the figure:

Business timing analysis and design

The client sends a deletion request to the server, and the processing sequence of the server is as follows:

Design and implementation of deletion method in data logical object (DAO)

Based on the business, add and delete methods in BrandDao interface. The code is as follows:

int deleteById(Integer id);

Based on the deletion method, define the SQL mapping (this time, it is defined directly in the form of annotation). The code is as follows:

@Delete("delete from tb_brand where id=#{id}")
int deleteById(Integer id);

Add a unit test method in BrandDaoTests unit test class to test the deletion. The key codes are as follows

@Test
void testDeleteById(){
    int rows=brandDao.deleteById(10);
    System.out.println("rows="+rows);
}

Design and implementation of deletion method in business logic object (Service)

In the business logic object method, some business logic (parameter verification, permission control,...) required for deletion operation should be handled

Step 1: add and delete the brand business method in the BrandService interface. The code is as follows:

int deleteById(Integer id);

Step 2: add and delete the specific implementation of business in BrandServiceImpl class. The code is as follows:

public int deleteById(Integer id){
     //1. Parameter verification
     //2. Execute delete business
     int rows=brandDao.deleteById(id);
     //3. Verify the result and return it
     return rows;
} 

Step 3: add a unit test method to the BrandServiceTests class to test its deletion business?

@Test
void testDeleteById(){
     int rows=brandService.deleteById(10);
     System.out.println("row="+row);
}

Step 4: Bug analysis during testing?

Design and implementation of deletion method in control logic object (Controller)

Define the method to process the deletion request in the control layer object. The specific code is as follows:

@GetMapping("/brand/doDeleteById/{id}")
public String doDeleteById(@PathVariable Integer id,Model model){
      brandService.deleteById(id);
      List<Brand> list=brandService.findBrands();
      model.addAttribute("list",list);
      return "brand/brand";
} 

Client delete button event definition and handling

Add a column in tr of tbody with the following code:

<td>
 <button type="button" th:onclick="doDeleteById([[${brand.id}]])">delete</button>
</td>

Define javascript functions to handle deletion events. The code is as follows:

function doDeleteById(id){
    //Give prompt information
 if(!confirm("Are you sure to delete"))return;//confirm is a function of the window object in the browser
 //Execute delete business
 location.href=`http://localhost/brand/doDeleteById/${id}`;
}

Analysis and implementation of brand module adding business

Business description

On the list page, design the Add button. When you click the Add button, jump to the add page, and then on the add page, the data brand information, click the Save button to submit the data to the server for saving

Add timing analysis and design

Design and implementation of method in data logical object (Dao)

Step 1: add a method to save brand information in BrandDao. The code is as follows:

int insertBrand(Brand brand);

Step 2: add the sql map corresponding to the brand saving operation in BrandMapper. The code is as follows:

<insert id="insertBrand">
     insert into tb_brand 
     (name,remark,createdTime)
     values
     (#{name},#{remark},now())
</insert>

Design and implementation of method in business logic object (Service)

Step 1: define the method for saving brand information in BrandService business interface. The code is as follows:

int saveBrand(Brand brand);

Step 2: add the specific implementation of saving brand information in BrandServiceImpl business implementation class. The code is as follows:

public int saveBrand(Brand brand){
    int rows=brandDao.insertBrand(brand);
    return rows;
}

Design and implementation of method in control logic object (Controller)

Step 1: add a method to handle the page request in BrandController. The code is as follows:

@GetMapping("/brand/doAddUI")
public String doAddUI(){
    return "brand/brand-add";
}

Step 2: add a method for processing the page of adding brand information in BrandController. The code is as follows:

@PostMapping("/brand/doSaveBrand")
public String doSaveBrand(Brand brand,Model model){
    System.out.println("save.brand="+brand);
    brandService.saveBrand(brand);
    List<Brand> list=brandService.findBrands(null);
    model.addAttribute("list",list);
    return "brand/brand";
}

Brand addition operation client business analysis, design and implementation

Step 1: design the brand addition page brand add HTML, the code is as follows

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/bootstrap/css/bootstrap.css">
</head>
<body>
   <div class="container">
       <h1>The Brand Add Page</h1>
       <form th:action="@{/brand/doSaveBrand}" method="post">
           <div class="form-group">
               <label for="nameId">Name</label>
               <input type="text" class="form-control" name="name" id="nameId" placeholder="Brand Name">
           </div>
           <div class="form-group">
               <label for="remarkId">Remark</label>
               <textarea class="form-control" rows="5" cols="100" name="remark" id="remarkId">
               </textarea>
           </div>
           <button type="submit" class="btn btn-default">Submit</button>
       </form>
   </div>
</body>
</html>

Step 2: in the brand list brand HTML page, design the Add button, and the code is as follows:

<button type="button" onclick="doAddUI()" class="btn btn-primary btn-sm">Add Brand</button>

Step 3: click the Add button to load the brand add page. The event handling function is as follows:

function doAddUI(){
    location.href="/brand/doAddUI";
}

Start the service for access test analysis

BUG analysis during startup and operation

  • Can't you get the data submitted by the client to the server?

Analysis and implementation of brand module modification business

Business description

On the brand list page, click the Modify button of the current line, first query the record of the current line based on the id, and present the record on the editing page, as shown in the figure:

Business timing analysis and design

Query the brand information based on id and present it on the page. The timing analysis is shown in the figure:

On the brand editing page, edit the data and click Save to save the update. The sequence is shown in the figure:

Design and implementation of method in data logical object (Dao)

Add the method of querying brand information based on id and SQL mapping in BrandDao. The code is as follows:

@Select("select * from tb_brand where id=#{id}")
Brand findById(Integer id);

Add the method of brand update based on id and SQL mapping in BrandDao. The code is as follows:

 @Update("update tb_brand set name=#{name},remark=#{remark} where id=#{id}")
 int updateBrand(Brand Brand);

Design and implementation of method in business logic object (Service)

Add the method of querying and updating brand information based on id in BrandService. The code is as follows:

Brand findById(Integer id);
int updateBrand(Brand brand);

In BrandServiceImpl, the method of querying and updating brand information based on id is as follows:

 @Override
    public Brand findById(Integer id) {
        //.....
        return brandDao.findById(id);
    }
 @Override
    public int updateBrand(Brand brand) {
        return brandDao.updateBrand(brand);
    }

Design and implementation of method in control logic object (Controller)

Add a method to query brand information based on id in BrandController. The code is as follows:

 @RequestMapping("/brand/doFindById/{id}")
    public String doFindById(@PathVariable Integer id,Model model) {
        Brand brand=brandService.findById(id);
        model.addAttribute("brand",brand);
        return "/brand/brand-update";
    }

Add the method of updating brand information in BrandController. The code is as follows:

 @RequestMapping("/brand/doUpdateBrand")
    public String doUpdateBrand(Brand brand,Model model) {
        brandService.updateBrand(brand);
        List<Brand> list=brandService.findBrands(null);
       model.addAttribute("list",list);
     return "brand/brand";
    }

Design and implementation of client brand editing page

Step 1: design the brand modification page brand update HTML, the code is as follows

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/bootstrap/css/bootstrap.css">
</head>
<body>
   <div class="container">
       <h1>The Brand Update Page</h1>
       <input type="hidden" name="id" th:value="${brand.id}">
       <form th:action="@{/brand/doUpdateBrand}" method="post">
           <div class="form-group">
               <label for="nameId">Name</label>
               <input type="text" class="form-control" name="name" id="nameId" th:value="${brand.name}" placeholder="Brand Name">
           </div>
           <div class="form-group">
               <label for="remarkId">Remark</label>
               <textarea class="form-control" rows="5" cols="100" name="remark" th:text="${brand.remark}" id="remarkId">
               </textarea>
           </div>
           <button type="submit" class="btn btn-default">Submit</button>
       </form>
   </div>
</body>
</html>

Start Tomcat service for access test analysis

Start the service, enter the brand list page first, and then click the Modify button, as shown in the figure:

At this time, enter the brand editing page, as shown in the figure:

On the brand editing page, after editing the data, click the save button to execute the update operation.

BUG analysis during startup and operation

  • 405 abnormal

  • The data presented is incorrect

  • Page element parsing exception

Tags: Mybatis Spring Spring Boot

Posted by wobbit on Wed, 04 May 2022 07:44:41 +0300