Premium Purchase (IDEA version) - Next day

Keywords: Java angular Mybatis log4j

Premium Purchase - Day 2

Learning Objectives

Goal 1: Common instructions for using the Angular JS front-end framework
Goal 2: Complete the list function of brand management
Goal 3: Complete Brand Management Paging List
Goal 4: Complete the added function of brand management
Goal 5: Complete the modification function of brand management
Goal 6: Complete the deletion function of brand management
Goal 7: Complete the conditional query function of brand management
Target N: Universal Mapper

Chapter 1 Introduction to the Front End Framework AngularJS

1.1 Introduction to Angular JS rJS

Angular JS was created in 2009 by Misko Hevery and others and acquired by Google.It is an excellent front-end JS framework that has been used in many products of Google.Angular JS has many features, the core of which are MVC, modularization, automatic two-way data binding, dependency injection and so on.

1.2 Four characteristics of Angular JS

1.2.1 MVC mode

Angular follows the MVC pattern of software engineering and encourages loosely coupled presentation, data, and logical components. By dependency injection, Angular brings traditional service-side services to client-side Web applications, such as view-independent control.As a result, the backend reduces many of the burden and produces lighter Web applications.

Model: Data is actually an angular variable ($scope.XX);

View: Data rendering, Html+Directive;

Controller: Operational data is function, data addition or deletion check;

1.2.2 Binding

Angular JS is built on the belief that declarative programming should be used to build user interfaces and write software builds, while instructional programming is well suited to represent business logic.The framework uses and extends traditional HTML to accommodate dynamic content through two-way data binding, which allows automatic synchronization between models and views.Therefore, Angular JS makes DOM operations less important and improves testability.

1.2.3 Dependent Injection

Dependency Injection (DI) is a design pattern in which other objects on which an object depends are not created manually but simply "roar" when it is created. The objects on which the object depends are automatically created and injected by the framework, which is actually the rule of least knowledge. All service and provider objects in a module can be named according to the parameter names.Implement DI.

1.2.4 Modular Design

High cohesion and low coupling rule

1) Official modules ng, ngRoute, ngAnimate

2) User-defined module angular.module('module name', [])

1.3 Getting Started Small Demo

1.3.1 expression
<html>
<head>
    <title>Getting Started Small Demo-1</title>
    <script src="angular.min.js"></script>
</head>
<body ng-app>
{{100+100}}
</body>
</html>

The results are as follows:

The expression is written as {{Expression}} The expression can be a variable or an expression

The ng-app directive tells child elements that the following directives belong to angular Js, which recognize them
The ng-app directive defines the root element of an Angular JS application.
The ng-app directive automatically boots (initializes) the application when the page is loaded.

1.3.2 Binding
<html>
<head>
    <title>Getting Started Small Demo-1  Binding in both directions</title>
    <script src="angular.min.js"></script>
</head>
<body ng-app>
//Please enter your name: <input ng-model="myname">
<br>
{{myname}},Hello
</body>
</html>

The results are as follows:

The ng-model directive binds variables so that what the user enters in the text box is bound to the variable, and the expression outputs the variable in real time.

1.3.3 Initialization Instructions

If you want some variables to have initial values, you can use the ng-init directive to initialize the variables:

<html>
<head>
    <title>Getting Started Small Demo-3  Initialization</title>
    <script src="angular.min.js"></script>
</head>
<body ng-app   ng-init="myname='Chen Dahai'">
//Please enter your name: <input ng-model="myname">
<br>
{{myname}},Hello
</body>
</html>
1.3.4 Controller
<html>
<head>
    <title>Getting Started Small Demo-3  Initialization</title>
    <script src="angular.min.js"></script>
    <script>
        var app=angular.module('myApp',[]); //A module called myApp is defined
        //Define Controller
        app.controller('myController',function($scope){
            $scope.add=function(){
                return parseInt($scope.x)+parseInt($scope.y);
            }
        });
    </script>
</head>
<body ng-app="myApp" ng-controller="myController">
x:<input ng-model="x" >
y:<input ng-model="y" >
//Operation result: {{add()}}
</body>
</html>

The results are as follows:

ng-controller is used to specify the controller used.

Understand $scope:

The use of $scope runs through the entire Angular JS App application and is associated with the data model as well as the context in which the expression is executed.With $scope, a channel is established between the view and the controller that updates the $scope as soon as the data is modified based on the scope view, and the view is re-rendered as soon as the $scope changes.

1.3.5 Event directives
<html>
<head>
    <title>Getting Started Small Demo-5  Event directives</title>
    <script src="angular.min.js"></script>  
    <script>
        var app=angular.module('myApp',[]); //A module called myApp is defined
        //Define Controller
        app.controller('myController',function($scope){         
            $scope.add=function(){
                $scope.z= parseInt($scope.x)+parseInt($scope.y);
            }           
        }); 
    </script>
</head>
<body ng-app="myApp" ng-controller="myController">
x:<input ng-model="x" >
y:<input ng-model="y" >
<button ng-click="add()">operation</button>
//Result: {{z}}
</body>
</html>

Run result:

ng-click is one of the most common click event directives that triggers a controller when clicked

1.3.6 Loop Array
<html>
<head>
    <title>Getting Started Small Demo-6  Cyclic data</title>
    <script src="angular.min.js"></script>
    <script>
        var app=angular.module('myApp',[]); //A module called myApp is defined
        //Define Controller
        app.controller('myController',function($scope){
            $scope.list= [100,192,203,434 ];//Define Array
        });
    </script>
</head>
<body ng-app="myApp" ng-controller="myController">
<table>
<tr ng-repeat="x in list">
    <td>{{x}}</td>
</tr>
</table>
</body>
</html>

The ng-repeat directive here is used to loop array variables.

The results are as follows:

1.3.7 Looping Object Array
<html>
<head>
    <title>Getting Started Small Demo-7  Loop Object Array</title>
    <script src="angular.min.js"></script>  
    <script>
        var app=angular.module('myApp',[]); //A module called myApp is defined
        //Define Controller
        app.controller('myController',function($scope){     
            $scope.list= [
                {name:'Zhang San',shuxue:100,yuwen:93},
                {name:'Li Si',shuxue:88,yuwen:87},
                {name:'King Five',shuxue:77,yuwen:56}
            ];//Define Array            
        }); 
    </script>   
</head>
<body ng-app="myApp" ng-controller="myController">
<table>
<tr>
    <td>Full name</td>
    <td>Mathematics</td>
    <td>Chinese</td>
</tr>
<tr ng-repeat="entity in list">
    <td>{{entity.name}}</td>
    <td>{{entity.shuxue}}</td>
    <td>{{entity.yuwen}}</td>
</tr>
</table>
</body>
</html>

The results are as follows:

1.3.8 Built-in Services

We usually get our data from the back end, so how do we get it?We typically use the built-in service, $http.Note: The following code needs to be run in tomcat.

<html>
<head>
    <title>Getting Started Small Demo-8  Built-in Services</title>
    <meta charset="utf-8" />
    <script src="angular.min.js"></script>  
    <script>
        var app=angular.module('myApp',[]); //A module called myApp is defined
        //Define Controller
        app.controller('myController',function($scope,$http){       
            $scope.findAll=function(){
                $http.get('data.json').success(
                    function(response){
                        $scope.list=response;
                    }                   
                );              
            }           
        }); 
    </script>   
</head>
<body ng-app="myApp" ng-controller="myController" ng-init="findAll()">
<table>
<tr>
    <td>Full name</td>
    <td>Mathematics</td>
    <td>Chinese</td>
</tr>
<tr ng-repeat="entity in list">
    <td>{{entity.name}}</td>
    <td>{{entity.shuxue}}</td>
    <td>{{entity.yuwen}}</td>
</tr>
</table>
</body>
</html>

Create file data.json

[
    {"name":"Zhang San","shuxue":100,"yuwen":93},
    {"name":"Li Si","shuxue":88,"yuwen":87},
    {"name":"King Five","shuxue":77,"yuwen":56},
    {"name":"Zhao Six","shuxue":67,"yuwen":86}
]

Chapter 2 General Mapper

2.1 Introduction to Universal Mapper

Universal Mapper provides some common methods, which are provided in the form of interfaces. It simplifies the form operation problems that we often do in our work, and makes MyBatis from process-oriented to object-oriented. Of course, writing SQL process-oriented operations and general Mapper object-oriented operations can coexist.

For testing purposes, we introduced the log log package in the parent project with the following versions:

<slf4j.version>1.6.6</slf4j.version>
<log4j.version>1.2.12</log4j.version>

The package was introduced as follows:

<!-- log start -->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>${log4j.version}</version>
</dependency>

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>${slf4j.version}</version>
</dependency>

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>${slf4j.version}</version>
</dependency>
<!-- log end -->

log4j.properties

log4j.rootLogger=DEBUG,Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
log4j.logger.org.apache=DEBUG

2.2 Configuration Introduction

Using a generic generic Mapper first requires the introduction of dependent packages.

<!--currency Mapper-->
<dependency>
    <groupId>tk.mybatis</groupId>
    <artifactId>mapper</artifactId>
</dependency>

Replace the package scan bean for MyBatis integrated Spring and modify the spring-mybatis.xml in the pinyougou-mapper project

Before replacement:

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"
   p:basePackage="com.pinyougou.mapper"
     p:sqlSessionFactoryBeanName="sqlSessionFactoryBean" />

After replacement:

<bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer"
     p:basePackage="com.pinyougou.mapper"
     p:sqlSessionFactoryBeanName="sqlSessionFactoryBean">
   <!--Common Interface-->
   <property name="properties">
      <value>
         mappers=tk.mybatis.mapper.common.Mapper
      </value>
   </property>
</bean>

2.3 MyBatis+Universal Mapper+Spring Integration Test

Writing test classes in pinyougou-sellergoods-service

package com.pinyougou;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MapperTest {
    private ApplicationContext act;
    @Before
    public void init(){
        act = new ClassPathXmlApplicationContext("classpath:spring/spring.xml");
    }
    @Test
    public void testSpring(){
        String[] names = act.getBeanDefinitionNames();

        for (String name : names) {
            System.out.println(name);
        }
    }
}

test result

addressMapper
areasMapper
brandMapper
citiesMapper
contentCategoryMapper
contentMapper
freightTemplateMapper
goodsDescMapper
goodsMapper
itemCatMapper
itemMapper
orderItemMapper
orderMapper
payLogMapper
provincesMapper
seckillGoodsMapper
seckillOrderMapper
sellerMapper
specificationMapper
specificationOptionMapper
typeTemplateMapper
userMapper

Here you can see that each interface produces a proxy object and is injected into the Spring container, and each interface inherits the Mapper interface, so it's preliminary to conclude that inheriting the generic Mapper succeeds, and then we'll use the generic Mapper for add-delete check.

2.4 Use of Universal Mapper

2.4.1 Add Operation
2.4.1.1 Do not ignore null-insert
/***
 * Add data
 * Do not ignore null values
 */
@Test
public void testInsert(){
    Brand brand = new Brand();
    brand.setName("Shenzhen Black Horse Training Camp");
    //brand.setFirstChar("C");
    int acount = brandMapper.insert(brand);
    System.out.println(acount);
}

Journal:

When Brand's id and firstChar are empty, the SQL statement still performs the insert operation.

==>  Preparing: INSERT INTO tb_brand ( id,name,first_char ) VALUES( ?,?,? ) 
==> Parameters: null, Shenzhen Black Horse Training Camp(String), null
1.4.1.2. Ignore null-insertSelective
/***
 * Add data
 * Ignore null values
 */
@Test
public void testInsertSelective(){
    Brand brand = new Brand();
    brand.setName("Wise Podcast-Black Horse Training Camp");
    //brand.setFirstChar("C");
    int acount = brandMapper.insertSelective(brand);
    System.out.println(acount);
}

Journal:

When Brand's id and firstChar are empty, the SQL statement does not perform an insert operation.

==>  Preparing: INSERT INTO tb_brand ( name ) VALUES( ? ) 
==> Parameters: Podcast-Black Horse Training Camp (String)
2.4.2 Modification Operations
2.4.2.1 Modify data based on primary key - do not ignore null values
/**
 * Action needs to be changed
 * Do not ignore null values
 */
@Test
public void testUpdateByPrimaryKey(){
    Brand brand = new Brand();
    brand.setId(25L);
    //Brand.setName (Shenzhen Black Horse Training Camp);
    brand.setFirstChar("S");
    //Modify data based on primary key
    int mcount = brandMapper.updateByPrimaryKey(brand);
    System.out.println(mcount);
}

Journal:

When the name is empty, the SQL statement still performs the modification.

==>  Preparing: UPDATE tb_brand SET name = ?,first_char = ? WHERE id = ? 
==> Parameters: null, S(String), 25(Long)
2.4.2.2. Modify data based on primary key - ignore null values
/**
 * Action needs to be changed
 * Ignore null values
 */
@Test
public void testUpdateByPrimaryKeySelective(){
    Brand brand = new Brand();
    brand.setId(25L);
    brand.setName("Shenzhen Black Horse Training Camp");
    //brand.setFirstChar("S");
    //Modify data based on primary key
    int mcount = brandMapper.updateByPrimaryKeySelective(brand);
    System.out.println(mcount);
}

Journal:

The SQL statement does not perform modifications when the name is empty.

1
2
3
sql
==>  Preparing: UPDATE tb_brand SET name = ? WHERE id = ? 
==> Parameters: Shenzhen Black Horse Training Camp(String), 25(Long)
2.4.2.3 Construction Conditions Modify Data - Do not Ignore Nulls
/**
 * Construct Conditions Execute Modifications
 * Do not ignore null values
 */
@Test
public void testUpdateByExample(){
    //firstChar=S
    Brand brand = new Brand();
    brand.setName("Shenzhen Black Horse Training Camp");

    //Create Example Object
    Example example = new Example(Brand.class);

    //Criteria is used to construct constraints
    Example.Criteria criteria = example.createCriteria();

    //The first parameter is the property corresponding to Brand, and the second parameter is the property constraint value equivalent to where firstChar=S
    criteria.andEqualTo("firstChar","S");

    //Conditional Modification Data
    int mcount = brandMapper.updateByExample(brand,example);
    System.out.println(mcount);
}

Journal:

criteria.andEqualTo("firstChar", "S"); converted to the SQL statement where(first_char=?), where firstChart is empty, but the SQL statement still executes the modifications.

1
2
==>  Preparing: UPDATE tb_brand SET name = ?,first_char = ? WHERE ( first_char = ? ) 
==> Parameters: Shenzhen Black Horse Training Camp(String), null, S(String)
2.4.2.4 Construction Conditions Modify Data - Ignore Null Values
/**
 * Construct Conditions Execute Modifications
 * Ignore null values
 */
@Test
public void testUpdateByExampleSelective(){
    //firstChar=S
    Brand brand = new Brand();
    brand.setFirstChar("S");
    //Create Example Object
    Example example = new Example(Brand.class);
    //Criteria is used to construct constraints
    Example.Criteria criteria = example.createCriteria();

    //The first parameter is the attribute corresponding to Brand, and the second parameter is the attribute constraint value equivalent to where name='Shenzhen Black Horse Training Camp'
    criteria.andEqualTo("name","Shenzhen Black Horse Training Camp");

    //Conditional Modification Data
    int mcount = brandMapper.updateByExampleSelective(brand,example);
    System.out.println(mcount);
}

Journal:

The name here is empty and the SQL statement has not been modified.

==>  Preparing: UPDATE tb_brand SET first_char = ? WHERE ( name = ? ) 
==> Parameters: S(String), Shenzhen Black Horse Training Camp(String)
2.4.3 Query Operations
1.4.3.1. Query by primary key
/***
 * Query by Primary Key
 */
@Test
public void testSelectByPrimaryKey(){
    long id = 25L;
    Brand brand = brandMapper.selectByPrimaryKey(id);
    System.out.println(brand);
}

Journal:

==>  Preparing: SELECT id,name,first_char FROM tb_brand WHERE id = ? 
==> Parameters: 25(Long)
Brand{id=25, name='Shenzhen Black Horse Training Camp', firstChar='S'}
2.4.3.1 Query Single Record
/***
 * Query individual records
 */
@Test
public void testSelectOne(){
    Brand brand = new Brand();
    brand.setId(25L);
    brand.setName("Shenzhen Black Horse Training Camp");
    Brand brand1 = brandMapper.selectOne(brand);
    System.out.println(brand1);
}

Journal:

==>  Preparing: SELECT id,name,first_char FROM tb_brand WHERE id = ? AND name = ? 
==> Parameters: 25(Long), Shenzhen Black Horse Training Camp(String)
Brand{id=25, name='Shenzhen Black Horse Training Camp', firstChar='S'}

Be careful:

It is important to note that the data for this condition must be <=1 in the database, and if it is greater than 1, an error will be reported.

TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 3
2.4.3.2 Query by Conditions-Example
/***
 * Execute queries based on conditions
 */
@Test
public void testExample(){
    Example example = new Example(Brand.class);
    Example.Criteria criteria = example.createCriteria();
    //id IN(1,2,5,6)
    List<Long> ids = new ArrayList<Long>();
    ids.add(1L);
    ids.add(2L);
    ids.add(5L);
    ids.add(6L);

    //The second parameter is a collection object. Note that the type corresponding to the collection object here, although Object, is the same as the type corresponding to your database.
    criteria.andIn("id",ids);

    //Execute Query
    List<Brand> brands = brandMapper.selectByExample(example);

    for (Brand brand : brands) {
        System.out.println(brand);
    }
}

Journal:

==>  Preparing: SELECT id,name,first_char FROM tb_brand WHERE ( id in ( ? , ? , ? , ? ) ) 
==> Parameters: 1(Long), 2(Long), 5(Long), 6(Long)
Brand{id=1, name='association', firstChar='L'}
Brand{id=2, name='Huawei', firstChar='H'}
Brand{id=5, name='OPPO', firstChar='O'}
Brand{id=6, name='Shenzhen Black Horse Training Camp', firstChar='S'}
2.4.3.3 Conditional Query-JavaBean
/***
 * Query by condition
 * Include: JavaBean
 */
@Test
public void testSelect(){
    Brand brand = new Brand();
    brand.setId(25L);
    brand.setName("Shenzhen Black Horse Training Camp");
    //Use brand as a query condition, and null values are ignored here
    List<Brand> brands = brandMapper.select(brand);
    for (Brand bd : brands) {
        System.out.println(bd);
    }
}

Journal:

==>  Preparing: SELECT id,name,first_char FROM tb_brand WHERE id = ? AND name = ? 
==> Parameters: 25(Long), Shenzhen Black Horse Training Camp(String)
Brand{id=25, name='Shenzhen Black Horse Training Camp', firstChar='S'}
2.4.3.4 Query All
/***
 * Query all
 */
@Test
public void testSelectAll(){
    //Execute Query
    List<Brand> brands = brandMapper.selectAll();

    for (Brand brand : brands) {
        System.out.println(brand);
    }
}

Journal:

==>  Preparing: SELECT id,name,first_char FROM tb_brand 
==> Parameters: 
Brand{id=1, name='association', firstChar='L'}
Brand{id=2, name='Huawei', firstChar='H'}
Brand{id=3, name='Shenzhen Black Horse Training Camp', firstChar='S'}
...........................................
2.4.3.5 Statistical Query
/***
 * Statistical Queries - Total Records
 */
@Test
public void testSelectCount(){
    //Total number of records queried
    int count = brandMapper.selectCount(null);
    System.out.println(count);
}

Journal:

==>  Preparing: SELECT COUNT(id) FROM tb_brand 
==> Parameters: 
25
2.4.4 Delete operation
2.4.4.1 Delete by Primary Key
/***
 * Delete by ID
 */
@Test
public void testDeleteByPrimaryKey(){
    long id = 25;
    int dcount = brandMapper.deleteByPrimaryKey(id);
    System.out.println(dcount);
}

Journal:

==>  Preparing: DELETE FROM tb_brand WHERE id = ? 
==> Parameters: 25(Long)
2.4.4.2 Conditional Delete-Example
/***
 * Conditional Delete
 */
@Test
public void testDeleteByExample(){
    Example example = new Example(Brand.class);
    Example.Criteria criteria = example.createCriteria();
    //where id between 23 and 28
    criteria.andBetween("id",23L,28L);
    //Delete by condition
    int dcount = brandMapper.deleteByExample(example);
    System.out.println(dcount);
}

Journal:

==>  Preparing: DELETE FROM tb_brand WHERE ( id between ? and ? ) 
==> Parameters: 23(Long), 28(Long)
2.4.4.3 Conditional Delete-JavaBean
/***
 * Conditional Delete
 * Include: javaBean
 */
@Test
public void testDelete(){
    Brand brand = new Brand();
    brand.setName("Avatar");
    //Delete by condition
    int dcount = brandMapper.delete(brand);
    System.out.println(dcount);
}

Journal:

==>  Preparing: DELETE FROM tb_brand WHERE name = ? 
==> Parameters: Avatar(String)

Chapter 3 Paging Tools

Paging is common when working on projects, but often involves tedious packaging.A universal paging plugin, pagehelper, is provided to meet the basic needs of our work.

3.1 Configuration Introduction

First, you need to introduce corresponding dependencies

<!--Paging Toolkit-->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
</dependency>

Then you need to configure a mybatis interceptor to include the following plug-in code in mybatis.xml of the pinyougou-mapper project

<plugins>
    <!-- com.github.pagehelper by PageInterceptor Package name in which the class resides -->
    <plugin interceptor="com.github.pagehelper.PageInterceptor">
        <property name="reasonable" value="true"/>
    </plugin>
</plugins>

The above configuration can be either not configured in mybatis.xml or in the SqlSessionFactoryBean of spring-mybatis.xml with the following code:

<!-- SqlSessionFactoryBean -->
<bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="configLocation" value="classpath:mybatis/mybatis.xml" />
    <property name="typeAliasesPackage" value="com.pinyougou.model" />
    <property name="mapperLocations">
        <list>
            <value>classpath:com/pinyougou/mapper/*Mapper.xml</value>
        </list>
    </property>
    <property name="dataSource" ref="dataSource" />

    <!--Paging Plugin Configuration-->
    <property name="plugins">
        <array>
            <bean class="com.github.pagehelper.PageInterceptor">
                <!--Configure Paging Properties-->
                <property name="properties">
                    <props>
                        <!--Specify database dialect-->
                        <prop key="helperDialect">mysql</prop>
                        <!--Rationalize Paging Operations-->
                        <prop key="reasonable">true</prop>
                    </props>
                </property>
            </bean>
        </array>
    </property>
</bean>

3.2 Paging Class Introduction

The PageInfo class contains both paging information in our work and collection objects for paging queries, so it is useful as follows:

public class PageInfo<T> implements Serializable {
    private static final long serialVersionUID = 1L;
    //Current Page
    private int pageNum;
    //Number of pages per page
    private int pageSize;
    //Number of current pages
    private int size;
    //Line number of the first element of the current page in the database
    private int startRow;
    //The row number of the last element of the current page in the database
    private int endRow;
    //Total Records
    private long total;
    //PageCount
    private int pages;
    //Result Set
    private List<T> list;
    //next page before
    private int prePage;
    //next page
    private int nextPage;
    //Is it the first page
    private boolean isFirstPage = false;
    //Is it the last page
    private boolean isLastPage = false;
    //Is there a previous page
    private boolean hasPreviousPage = false;
    //Is there a next page
    private boolean hasNextPage = false;
    //Number of navigation pages
    private int navigatePages;
    //All navigation page numbers
    private int[] navigatepageNums;
    //First page on navigation bar
    private int navigateFirstPage;
    //Last page on navigation bar
    private int navigateLastPage;
     //........Omitted
}

3.3 Use of Paging Plugins

Paging plug-ins are simple to use. Once configured, paging can be achieved by calling PageHelper's static method startPage directly. Other queries can be written normally. Note that the method calling startPage must be written before executing the query selectAll(), otherwise paging is invalid.

/**
 * Paging Test
 */
@Test
public void testPage(){
    //How many pages the current page size shows per page
    int page = 1,size=10;
    //Paging is done by simply calling the PageHelper.startPage static method.S
    PageHelper.startPage(page,size);

    //query
    List<Brand> brands = brandMapper.selectAll();

    //Get the paging information, notice that the brands collection object is passed in here
    PageInfo<Brand> pageInfo = new PageInfo<Brand>(brands);
    System.out.println(pageInfo);
}

Journal:

==>  Preparing: SELECT count(0) FROM tb_brand 
==> Parameters: 
------------------------------------------------------------------------------------------------------------------------------------------------
==>  Preparing: SELECT id,name,first_char FROM tb_brand LIMIT ? 
==> Parameters: 10(Integer)
------------------------------------------------------------------------------------------------------------------------------------------------
PageInfo{pageNum=1, pageSize=10, size=10, startRow=1, endRow=10, total=22, pages=3, list=Page{count=true, pageNum=1, pageSize=10, startRow=0, endRow=10, total=22, pages=3, reasonable=true, pageSizeZero=false}, prePage=0, nextPage=2, isFirstPage=true, isLastPage=false, hasPreviousPage=false, hasNextPage=true, navigatePages=8, navigateFirstPage=1, navigateLastPage=3, navigatepageNums=[1, 2, 3]}

Chapter 4 Implementation of Brand List

Brand paging implementation, remember to introduce paging packages in pinyougou-sellergoods-interface

<!--Paging Toolkit-->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
</dependency>

4.1 Demand Analysis

Implement a query of the brand list (without paging and conditional queries) as follows:

4.2 Front End Code

4.2.1 Copy Resources

Copy page resources under Resource/Static Prototype/Operator Management Background to pinyougou-manager-web

The plugins folder contains common front-end libraries such as angular JS, bootstrap, JQuery, and so on, which we will use in our project

4.2.2 Introduction of JS

Modify brand.html to introduce JS

<script src="/plugins/angularjs/angular.min.js"></script>

Specify modules and controllers

<body ng-app="pinyougou" ng-controller="brandController" class="hold-transition skin-red sidebar-mini">

The name of the module is defined in the ng-app directive

The ng-controller directive is used to add a controller to your application.

In the controller, you can write code, make functions and variables, and use scope objects to access them.

4.2.3 Writing JS code
<script>
   /******
   * 1,Introducing angular JS
   * 2,Send Request
   * 3,Display data
   *****/

   //Define a module
   var app = angular.module("pinyougou",[]);

   /*****
    * Define a controller
    * Send an HTTP request to get data from the background
    ****/
   app.controller("brandController",function($scope,$http){
      //Create a method
      //Get all the brand information
      $scope.getPage=function(page,size){
         //Send a request for data
         $http.post("/brand/list.shtml?page="+page+"&size="+size).success(function(response){
            //Collection data
            $scope.list = response.list;
         });
      }
   });
</script>
4.3.4 Cyclic display of tabular data
<tbody>
<tr ng-repeat="entity in list">
   <td><input  type="checkbox" ng-model="id" ></td>
   <td>{{entity.id}}</td>
   <td>{{entity.name}}</td>
   <td>{{entity.firstChar}}</td>
   <td class="text-center">
      <button type="button" class="btn bg-olive btn-xs" data-toggle="modal" data-target="#EditModal "> Modify </button>
   </td>
</tr>
</tbody>

4.3.5 Initialization Call

<body ng-app="pinyougou" ng-controller="brandController" ng-init="getPage(1,10)" class="hold-transition skin-red sidebar-mini">

Chapter 5 Realization of Brand List Paging

5.1 Demand Analysis

Place Paging Bar under Brand Management for Paging

5.2 Backend Code

5.2.1 Service Interface Layer

Add method definition in BrandService.java of pinyougou-sellergoods-interface

/***
 * Paging Back to List
 * @param pageNum
 * @param pageSize
 * @return
 */
public PageInfo<Brand> getAll(int pageNum, int pageSize);
5.2.2 Service Implementation Layer

Implement this method in BrandServiceImpl.java of pin y ougou-sellergoods-service:

public PageInfo<Brand> getAll(int pageNum, int pageSize) {
    //Execute Paging
    PageHelper.startPage(pageNum,pageSize);
    //List<Brand> all = brandMapper.getAllBrand();
    List<Brand> all = brandMapper.selectAll();

    PageInfo<Brand> pageInfo = new PageInfo<Brand>(all);
    return pageInfo;
}

PageHelper is MyBatis Paging Plugin

5.2.3 Control Layer

New method for BrandController.java in pinyougou-manager-web project

/***
 * Paging Query Data
 * Getting JSON data
 * @return
 */
@RequestMapping(value = "/list")
public PageInfo<Brand> list(@RequestParam(value = "page", required = false, defaultValue = "1") int page,
                            @RequestParam(value = "size", required = false, defaultValue = "10") int size) {
    return brandService.getAll(page, size);
}

5.3 Front End Code Control Layer

5.3.1 HTML

Introducing paging components in brand.html

<!--Paging related introduction-->
<link rel="stylesheet" href="/plugins/angularjs/pagination.css">
<script src="/plugins/angularjs/pagination.js"></script>

Introducing pagination module when building app module

//Define a module
var app = angular.module("pinyougou",["pagination"]); //Introducing Paging Modules

Place the paging component under the table of the page

<!--paging-->
<tm-pagination conf="paginationConf"></tm-pagination>
5.3.2 JS Code

Add the following code to the brandController

/***
 * Paging Control Configuration
 * currentPage:Current Page
 * totalItems:How many records are there
 * itemsPerPage:pagesize
 * perPageOptions:How many option bars per page
 * onChange:Execute when parameters change
 * */
$scope.paginationConf = {
   currentPage: 1,
   totalItems: 10,
   itemsPerPage: 10,
   perPageOptions: [10, 20, 30, 40, 50],
   onChange: function(){
      $scope.reloadList();//Reload
   }
};
//Reload
$scope.reloadList=function(){
   $scope.getPage($scope.paginationConf.currentPage,$scope.paginationConf.itemsPerPage);
}

Remove the call to the ng-init instruction from the body element of the page

<body ng-app="pinyougou" ng-controller="brandController" class="hold-transition skin-red sidebar-mini">
5.3.3 Complete Code
<script>
   /******
    * Step analysis:
    * 1,Introducing angular JS
    * 2,Send Request
    * 3,Display data
    *****/
    //Define a module
   var app = angular.module("pinyougou",["pagination"]);

   /*****
    * Define a controller
    * Send an HTTP request to get data from the background
    ****/
   app.controller("brandController",function($scope,$http){
      /***
       * Paging Control Configuration
       * currentPage:Current Page
       * totalItems:How many records are there
       * itemsPerPage:pagesize
       * perPageOptions:How many option bars per page
       * onChange:Execute when parameters change
       * */
      $scope.paginationConf = {
         currentPage: 1,
         totalItems: 10,
         itemsPerPage: 10,
         perPageOptions: [10, 20, 30, 40, 50],
         onChange: function(){
            $scope.reloadList();//Reload
         }
      };

      //Create a method
      //Get all the brand information
      $scope.getPage=function(page,size){
         //Send a request for data
         $http.post("/brand/list.shtml?page="+page+"&size="+size).success(function(response){
            //Collection data
            $scope.list = response.list;

            //Paging data
            $scope.paginationConf.totalItems=response.total;
         });
      }
      
      //Reload
      $scope.reloadList=function(){
         $scope.getPage($scope.paginationConf.currentPage,$scope.paginationConf.itemsPerPage);
      }
   });
</script>
5.3.4 Effect

Chapter 6 Brand Increase

6.1 Demand Analysis

Implement Brand Add Function

6.2 Backend Code

6.2.1 Control Layer

Add the add method to the BrandController of pinyougou-manager-web, along with the corresponding JSON data.

/***
 * Increase Brand Data
 * @param brand
 * Response data:success
 *                  true:Success false: failure
 *           message
 *                  Response message
 *
 */
@RequestMapping(value = "/add",method = RequestMethod.POST)
public Map<String,Object> add(@RequestBody Brand brand){
    //Store response messages
    Map<String,Object> dataMap = new HashMap<String,Object>();
    
    try {
        //Execution increase
        int acount = brandService.add(brand);

        if(acount>0){
            //Increase Success
            dataMap.put("success",true);
            dataMap.put("message","Increase Brand Success");
        }
    } catch (Exception e) {
        e.printStackTrace();
        dataMap.put("success",false);
        dataMap.put("message","Failed to increase brand");
    }
    return dataMap;
}
6.2.2 Service Interface Layer

New method definition in BrandService.java for pinyougou-sellergoods-interface

/***
 * Increase brand information
 * @param brand
 * @return
 */
int add(Brand brand);
6.2.3 Service Implementation Layer

Implement this method in BrandServiceImpl.java at com.pinyougou.sellergoods.service.impl

@Override
public int add(Brand brand) {
    return brandMapper.insertSelective(brand);
}

6.3 Front End Code

6.3.1 js code
//Add brand approach
$scope.save = function(){
   //Send Http requests, increase execution
   $http.post("/brand/add.shtml",$scope.entity).success(function(response){
      //Judging execution status
      if(response.success){
         //Reload new data
         $scope.reloadList();
      }else{
         //Print error message
         alert(response.message);
      }
   });
}
6.3.2 html code

Bind form elements, we use ng-model directives, bind button click events, we use ng-click

<!-- Edit window -->
<div class="modal fade" id="editModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
   <div class="modal-dialog" >
      <div class="modal-content">
         <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
            <h3 id="myModalLabel">Brand Editor</h3>
         </div>
         <div class="modal-body">
            <table class="table table-bordered table-striped"  width="800px">
               <tr>
                  <td>Brand name</td>
                  <td><input ng-model="entity.name" class="form-control" placeholder="Brand name" >  </td>
               </tr>
               <tr>
                  <td>Initials</td>
                  <td><input ng-model="entity.firstChar"  class="form-control" placeholder="Initials">  </td>
               </tr>
            </table>
         </div>
         <div class="modal-footer">
            <button ng-click="save()" class="btn btn-success" data-dismiss="modal" aria-hidden="true">Preservation</button>
            <button class="btn btn-default" data-dismiss="modal" aria-hidden="true">Close</button>
         </div>
      </div>
   </div>
</div>
6.3.3 Effect

6.4 Increase Cache Resolution

In order that each time the window opens without leaving the last data, we can modify the New button to empty the entity variable

<button ng-click="entity={}" type="button" class="btn btn-default" title="Newly build" data-toggle="modal" data-target="#EditModal "><i class=" fa-file-o "></i>New </button>

Effect

6.5 Encapsulate response message body

Introduction to 6.5.1 Packaging

We write a Map in response to the message body. Every time we need to use it, we create the Map object repeatedly, assign values to the specified key, there is a lot of duplicate code, and each key is easy to write incorrectly, so we can consider encapsulating it as an entity Bean, called Result, and directly new Result() each time.

6.5.2 Create Result

Since Result may be used in many projects, we can consider putting it in the pinyougou-common project and creating a Result class in pinyougou-common

package com.pinyougou.http;
import java.io.Serializable;
public class Result implements Serializable {

    private boolean success;

    private String message;

    public Result(boolean success, String message) {
        this.success = success;
        this.message = message;
    }

    public Result(boolean success) {
        this.success = success;
    }

    public Result(String message) {
        this.message = message;
    }

    public Result() {
    }

    //get.. set.. toString..
}
6.5.3 Dependency Analysis

No matter which project is directly or indirectly dependent on pinyougou-pojo, it makes sense for POJO to depend on pinyougou-common, maven to depend on transitivity, all projects will depend on pinyougou-common, and pinyougou-common is mainly used to write some commonly used toolkits, so it makes sense for any project to depend on him.

Add dependencies to pinyougou-pojo's pom.xml

<!--rely on pinyougou-common-->
<dependency>
    <artifactId>pinyougou-common</artifactId>
    <groupId>com.pinyougou</groupId>
    <version>1.0-SNAPSHOT</version>
</dependency>
6.5.4 Modify Controllerl

Modify the add method of BrandController in pinyougou-manager-web:

/***
 * Increase Brand Data
 * @param brand
 * Response data:success
 *                  true:Success false: failure
 *           message
 *                  Response message
 *
 */
@RequestMapping(value = "/add",method = RequestMethod.POST)
public Result add(@RequestBody Brand brand){
    try {
        //Execution increase
        int acount = brandService.add(brand);

        if(acount>0){
            //Increase Success
           return new Result(true,"Increase Brand Success");
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return new Result(false,"Failed to increase brand");
}

CHAPTER 7 REVISION OF BRAND

7.1 Demand Analysis

Click the Modify button of the list, pop-up window, and then click "Save" after modifying the data to perform the save operation, which is roughly divided into two steps.

First: Query out brand data based on ID and show it.

Second, save data according to user modifications.

7.2 Backend Code

7.2.1 Control Layer

Include methods to query and modify brands based on IDS in BrandController of pinyougou-manager-web

/***
 * Modify brand information
 * @param brand
 * @return
 */
@RequestMapping(value = "/update",method = RequestMethod.POST)
public Result modify(@RequestBody Brand brand){
    try {
        //Modify brand information based on ID
        int mcount = brandService.updateBrandById(brand);
        if(mcount>0){
            return new Result(true,"Brand Modification Successful");
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return new Result(false,"Brand Modification Failed");
}

/***
 * Query brand information based on ID
 * @param id
 * @return
 */
@RequestMapping(value = "/{id}",method = RequestMethod.GET)
public Brand getById(@PathVariable(value = "id")long id){
    //Query brand information based on ID
    Brand brand = brandService.getOneById(id);
    return brand;
}
7.2.2 Service Interface Layer

New method definition in BrandService.java for pinyougou-sellergoods-interface

/***
 * Query brand information based on ID
 * @param id
 * @return
 */
Brand getOneById(long id);

/***
 * Modify brand information based on ID
 * @param brand
 * @return
 */
int updateBrandById(Brand brand);
7.2.3 Service Implementation Layer

New method implementation in BrandServiceImpl.java for pinyougou-sellergoods-service

@Override
public Brand getOneById(long id) {
    return brandMapper.selectByPrimaryKey(id);
}

@Override
public int updateBrandById(Brand brand) {
    return brandMapper.updateByPrimaryKeySelective(brand);
}

7.3 Front End Code

7.3.1 Implementing Data Query

Add JS code;

//Query brand information based on ID
$scope.getById=function(id){
   $http.get("/brand/"+id+".shtml").success(function(response){
      //Bind background data to foreground
      $scope.entity=response;
   });
}

Modify the Modify button in the list to invoke this method to query entities

<button ng-click="getById(entity.id)" type="button" class="btn bg-olive btn-xs" data-toggle="modal" data-target="#EditModal ">Modify </button>
7.3.2 Saving Data

Modify JS save method

//Add or modify brand approach
$scope.save = function(){
   //Send Http requests, increase execution
   var url="/brand/add.shtml";
   if($scope.entity.id!=null){
      //Perform Modification Data
      url="/brand/update.shtml";
   }
   //Perform operation
   $http.post(url,$scope.entity).success(function(response){
      //Judging execution status
      if(response.success){
         //Reload new data
         $scope.reloadList();
      }else{
         //Print error message
         alert(response.message);
      }
   });
}

Chapter 8 Delete Brand

8.1 Demand Analysis

Click the check box in front of the list, click the Delete button, and delete the selected brand.

8.2 Backend Code

8.2.1 Control Layer

Add Delete Method to BrandController

/***
 * Bulk Delete Based on ID
 * @param ids
 * @return
 */
@RequestMapping(value = "/delete")
public Result delete(@RequestBody List<Long> ids){
    try {
        //Delete data based on ID
        int dcount = brandService.deleteByIds(ids);

        if(dcount>0){
            return new Result(true,"Brand Delete Success");
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return new Result(false,"Brand Deletion Failed");
}
8.2.2 Service Interface Layer

BrandService.java interface definition method in pinyougou-sellergoods-interface

/***
 * Delete brand information in batch based on ID
 * @param ids
 * @return
 */
int deleteByIds(List<Long> ids);
8.2.3 Service Implementation Layer

Implement this method in BrandServiceImpl.java of pinyougou-sellergoods-service

@Override
public int deleteByIds(List<Long> ids) {
    //Create an Example to build Delete Data by ID
    Example example = new Example(Brand.class);
    Example.Criteria criteria = example.createCriteria();

    //The required SQL statement is similar to delete from tb_brand where id in(1,2,5,6)
    criteria.andIn("id",ids);
    return brandMapper.deleteByExample(example);
}

8.3 Front End Code

8.3.1 js

Main idea: We need to define an array to store the selected ID. When we click on the check box, we decide whether to select or deselect, add it to the array if it is selected, and remove it from the array if it is unselected.This ID-stored array is needed when you click the Delete button.

Here we add some JS knowledge about Array Operations

push method for arrays: add elements to arrays

Array splice method: Removes a specified number of elements from a specified position in the array, with parameter 1 as the position and parameter 2 as the number of displacements

checked property of check box: Used to determine if it is selected:

//Define a variable to store the brand ID to be deleted
$scope.selectids=[];

//Determine if the current click will delete the corresponding brand
$scope.updateSelection=function($event,id){
   //Determine if the current action is checked
   if($event.target.checked){
      //If the check box is checked, the id is added to the array
      $scope.selectids.push(id);
   }else{
      //Cancel deletion, remove the id from the array
      var idx = $scope.selectids.indexOf(id);   //Get the subscript for the id
      $scope.selectids.splice(idx, 1);//Delete the data corresponding to the subscript, 1 indicating the number of deletions
   }
}


//Bulk Delete
$scope.delete=function(){
   $http.post("/brand/delete.shtml",$scope.selectids).success(function(response){
      //Determine Deletion Status
      if(response.success){
         $scope.reloadList();
      }else{
         alert(response.message);
      }
   });
}
8.3.2 HTML

Check box to modify list

<input  type="checkbox" ng-click="updateSelection($event,entity.id)" >

Modify Delete Button

<button ng-click="delete()" type="button" class="btn btn-default" title="delete" ><i class="fa fa-trash-o"></i> delete</button>

Chapter 9 Brand Conditions Query

9.1 Demand Analysis

Implement brand condition query function, enter brand name, first letter and then query, and page.

9.2 Backend Code

9.2.1 Control Layer

Modify the list method in BrandController

/***
 * Paging Query Data
 * Getting JSON data
 * @return
 */
@RequestMapping(value = "/list")
public PageInfo<Brand> list(@RequestBody Brand brand,@RequestParam(value = "page", required = false, defaultValue = "1") int page,
                            @RequestParam(value = "size", required = false, defaultValue = "10") int size) {
    return brandService.getAll(brand,page, size);
}
9.2.2 Service Interface Layer

BrandService.java method adds method definition in pinyougou-sellergoods-interface project

/***
 * Paging Back to List
 * @param pageNum
 * @param pageSize
 * @return
 */
public PageInfo<Brand> getAll(Brand brand,int pageNum, int pageSize);
9.2.3 Service Implementation Layer

Implement this method in the pinyougou-sellergoods-service project BrandServiceImpl.java

public PageInfo<Brand> getAll(Brand brand,int pageNum, int pageSize) {
    //Execute Paging
    PageHelper.startPage(pageNum,pageSize);

    //Conditional Query
    Example example = new Example(Brand.class);
    Example.Criteria criteria = example.createCriteria();

    if(brand!=null){
        //Name Ambiguous Search
        if(StringUtils.isNotBlank(brand.getName())){
            criteria.andLike("name","%"+brand.getName()+"%");
        }

        //Initial search
        if(StringUtils.isNotBlank(brand.getFirstChar())){
            criteria.andEqualTo("firstChar",brand.getFirstChar());
        }
    }
    //Execute Query
    List<Brand> all = brandMapper.selectByExample(example);
    PageInfo<Brand> pageInfo = new PageInfo<Brand>(all);


    //======================================================================
    //List<Brand> all = brandMapper.getAllBrand();
    /*List<Brand> all = brandMapper.selectAll();

    PageInfo<Brand> pageInfo = new PageInfo<Brand>(all);*/
    return pageInfo;
}

9.3 Front End Code

Modify brand.html for pinyougou-manager-web

9.3.1 Add Search Block

Add a search code block and bind a search object.Increase the click event and call the search method.

<div class="has-feedback">
   Brand name: <input ng-model="searchEntity.name">
   Brand initials: <input ng-model="searchEntity.firstChar">
   <button ng-click="getPage(1,10)" class="btn btn-default">query</button>
</div>
9.3.2 js

Define a search object that matches the search criteria and modify the original search method.

//Conditional Query Object Definition
$scope.searchEntity={};

//Get all the brand information
$scope.getPage=function(page,size){
   //Send a request for data
   $http.post("/brand/list.shtml?page="+page+"&size="+size,$scope.searchEntity).success(function(response){
      //Collection data
      $scope.list = response.list;

      //Paging data
      $scope.paginationConf.totalItems=response.total;
   });
}
9.3.3 Effect


Needed the next day Data Files

Posted by cstegner on Thu, 14 Nov 2019 12:28:40 -0800