Mybatis - mybatis general Mapper (Part B) of Data Access

2, General Mapper implements basic addition, deletion, modification and query BaseMapper

2.5 insert related methods

// When an entity is saved, the null attribute will also be saved. The default value of the database will not be used
int insert(T record);
// Save an entity. The null attribute will not be saved. The default value of the database will be used
int insertSelective(T record);
copy

2.5.1 insert method

Add save method in PorscheService

void save(Porsche porsche);
copy

Implementation of save method in PorscheServiceImpl

@Override
public void save(Porsche porsche) {
    porscheMapper.insert(porsche);
}
copy

Test the save method in PorscheServiceTest

@Test
public void save(){
    // Construct the inserted entity class
    Porsche porsche = new Porsche();
    porsche.setPorName("Panamera 4S 2022");
    porsche.setPorPrice(880000d);
    porsche.setPorStock(10);

    porscheService.save(porsche);
}
copy

Execute the save test method

The database has updated one row, and the insertion is successful. Add the test code, output the self increasing primary key, and execute the test again

The output primary key is null. The self increasing primary key has been generated after the actual insertion into the database, but the program has not obtained the primary key generated after the successful insertion. To obtain the generated primary key Value, you need to add @ GeneratedValue(strategy = GenerationType.IDENTITY) on the attribute corresponding to the Porsche entity class and the data primary key to execute the test again

Two SQL statements are executed, one is an insert statement, and the other is to query the Value of the latest primary key. The console successfully outputs the Value of the self increasing primary key generated after the successful insertion.

@The GeneratedValue annotation enables the general Mapper to write back the value of the self increasing primary key automatically generated by the database to the entity class after executing the insert operation

2.5.2 insertSelective method

Add savePorscheSelective method in PorscheService

void savePorscheSelective(Porsche porsche);
copy

Add the implementation of savePorscheSelective method in PorscheServiceImpl

@Override
public void savePorscheSelective(Porsche porsche) {
    porscheMapper.insertSelective(porsche);
}
copy

Add savePorscheSelective test method

@Test
public void savePorscheSelective(){
    Porsche porsche = new Porsche();
    porsche.setPorName("Porsche 911 2022");

    porscheService.savePorscheSelective(porsche);
}
copy

If the non primary key field is null, it will not be added to the SQL statement

It is suitable for the case where there are many entity class attributes, but there is less NULL data in the inserted attribute part when inserting

2.6 update related methods

// Update all fields of the entity according to the primary key, and the null value will be updated
int updateByPrimaryKey(T record);
// Update the non null value of the property according to the primary key
int updateByPrimaryKeySelective(T record);
copy

2.6.1 updateByPrimaryKeySelective

Add updatePorscheSelective method in PorscheService

void updatePorscheSelective(Porsche porsche);
copy

Add the implementation of updatePorscheSelective method in PorscheServiceImpl

@Override
public void updatePorscheSelective(Porsche porsche) {
    porscheMapper.updateByPrimaryKeySelective(porsche);
}
copy

Add updatePorscheSelective test method

@Test
public void updatePorscheSelective(){
    Porsche porsche = new Porsche();
    porsche.setPorId(1);
    porsche.setPorPrice(900000d);

    porscheService.updatePorscheSelective(porsche);
}
copy

Perform tests

For entity classes updated for some fields, use this method to update fields with values. Fields without values remain unchanged

2.7 delete related methods

// Delete according to the entity attribute as a condition, and the query condition uses an equal sign
int delete(T record);
// Delete according to the primary key field. The method parameter must contain the complete primary key attribute
int deleteByPrimaryKey(Object key);
copy

2.7.1 delete

Add the removePorsche method in Porsche service

void removePorsche(Porsche porsche);
copy

Add the implementation of removePorsche method in PorscheServiceImpl

@Override
public void removePorsche(Porsche porsche) {
    porscheMapper.delete(porsche);
}
copy

Added test method for removePorsche

@Test
public void removePorsche(){
    // Construct the entity class to be deleted
    Porsche porsche = new Porsche();
    porsche.setPorName("Panamera 4S 2022");
    porsche.setPorPrice(880000d);
    porsche.setPorStock(10);

    porscheService.removePorsche(porsche);
}
copy

Perform tests

If the passed object is null, comment out the setter method of the object and execute the test again

The data has been completely deleted. You must be careful and judge the conditions when using this method

2.7.2 deleteByPrimaryKey

Add the removePorscheById method in PorscheService

void removePorscheById(Integer id);
copy

Add the implementation of removePorscheById method in PorscheServiceImpl

@Override
public void removePorscheById(Integer id) {
    porscheMapper.deleteByPrimaryKey(id);
}
copy

Added removePorscheById test method

@Test
public void removePorscheById(){
    // Delete primary key of record
    Integer id = 1;
    porscheService.removePorscheById(id);
}
copy

Perform tests

deleteByPrimaryKey: the most commonly used deletion method

3, General Mapper to realize complex query - ExampleMapper

3.1 QBC query

QBC is Query By Criteria, and QBC query is to modularize and encapsulate query conditions through Java objects.

Criterion is an internal class. It is the plural form of criterion, which means standard; It is the same as the internal class code of criterion in the entity class CatExample of complex query conditions generated by MBG. It also provides the createCriteria method to create composite query conditions

The Example class of XXXExample VS general Mapper generated by MBG that encapsulates query conditions

Both encapsulate a large number of query conditions. The two methods are different. MBG directly generates XXXExample for Entity entity class, such as the generated CatExample and TeacherExample; When general Mapper uses conditional query, it needs to pass in an Entity class to query when creating an Example

Example porscheExample = new Example(Porsche.class);
copy

3.1.1 query using QBC

Use QBC to create the following composite query:

WHERE (por_id > 1 and por_stock > 20) OR ( por_price < 1000000 and por_stock > 20)
copy

Add getPorschesByPriceAndStock method in PorscheService

List<Porsche> getPorschesByPriceAndStock(Example porscheExample);
copy

Add the implementation of getPorschesByPriceAndStock method in PorscheServiceImpl

@Override
public List<Porsche> getPorschesByPriceAndStock(Example porscheExample) {

    return porscheMapper.selectByExample(porscheExample);
}
copy

Add the test method getPorscheByPriceAndStock in PorscheServiceTest, and view the comments during the construction of query conditions.

@Test
public void getPorscheByPriceAndStock(){
    Example porscheExample = new Example(Porsche.class);
    // WHERE (por_id > 1 and por_stock > 20) OR ( por_price < 1000000 and por_stock > 20)
    // Create two query conditions. The two parentheses behind the WHERE keyword correspond to two query conditions respectively
    Example.Criteria criteria1 = porscheExample.createCriteria();
    Example.Criteria criteria2 = porscheExample.createCriteria();
    // Set two query criteria:
    criteria1.andGreaterThan("porId",1)
            .andGreaterThan("porStock",20);

    criteria2.andLessThan("porPrice",1000000d)
            .andGreaterThan("porStock",20);

    // Connect query condition 1--criteria1 and query condition 2--criteria2 through OR
    // Porschample is equivalent to the select field name from, indicating WHERE criteria 1
    // Just call the or method to connect criteria2, and the completed SQL statement is formed
    // select field name from indicates WHERE (criteria1) OR (criteria2)
    porscheExample.or(criteria2);

    List<Porsche> porscheList = porscheService.getPorschesByPriceAndStock(porscheExample);
    for (Porsche porsche : porscheList) {
        System.out.println("The query contents are:" + porsche);
    }
}
copy

Perform tests

3.1.2 other QBC settings

QBC query can be set at the same time, such as sorting, de duplication, and setting query fields. Relevant codes are added in the getPorscheByPriceAndStock test method,

porscheExample.setDistinct(true);
porscheExample.orderBy("porPrice").asc().orderBy("porName").desc();
porscheExample.selectProperties("porName","porPrice");
copy

Perform the test again

View the SQL statements deleted by the console. The built composite conditions will take effect when the SQL is executed.

4, General Mapper implementation paging - RowBoundsMapper

4.1 paging related methods

// Perform paging query according to example conditions and rowboundaries
List<T> selectByExampleAndRowBounds(Object example, RowBounds rowBounds);

// Pagination query based on entity attributes and rowboundaries
List<T> selectByRowBounds(T record, RowBounds rowBounds);
copy

4.1.1 selectByRowBounds

Add the paging query method getPorschesByRowBounds in the PorscheService interface

List<Porsche> getPorschesByRowBounds(Porsche record, RowBounds rowBounds);
copy

Implement the paging query method getPorschesByRowBounds in PorscheServiceImpl

@Override
public List<Porsche> getPorschesByRowBounds(Porsche record, RowBounds rowBounds) {

    return porscheMapper.selectByRowBounds(record,rowBounds);
}
copy

Add the test code of this method

@Test
public void getPorschesByRowBounds(){
    int pageNo = 2;
    int pageSize = 3;

    int index = (pageNo - 1) * pageSize;

    RowBounds rowBounds = new RowBounds(index, pageSize);

    List<Porsche> porscheList = porscheService.getPorschesByRowBounds(null, rowBounds);

    for (Porsche porsche : porscheList) {
        System.out.println("The query contents are:" + porsche);
    }
}
copy

Perform tests

According to the SQL statement output by the console, it is indicated that the general Mapper still queries all data, and the paging operation in memory is "false paging". It is not recommended to use this paging query, and it is recommended to use the PageHelper plug-in to realize real paging

4.2 @Transient

In general, the attributes in the entity class correspond to the fields in the database table one-to-one. However, some attributes may not have corresponding fields in the database. In this case, you need to use the @ Transient annotation to indicate that this is not a field in the table.

5, Reverse engineering of general Mapper

5.1 reverse engineering of general Mapper

The code generated by reverse engineering of general Mapper is slightly different from the code generated by native MyBatis. First of all, it contains Entity entity class, XxxMapper interface and XxxMapper XML, but the Entity entity class generated by the general Mapper will contain annotations such as @ Table annotation, @ Column annotation, @ Id annotation and @ GeneratedValue; The generated XxxMapper interface inherits the Mapper < XXX > class; There is no SQL statement in the generated XxxMapper.xml, only a resultMap tag.

5.2 reverse engineering using general Mapper

Create a new project, common Mapper MBG. The dependencies, Spring configuration and MyBatis configuration used in this project are the same as those used in the general Mapper project. The difference is that the new general Mapper MBG project does not include the Entity class Mapper interface, Service class and test class.

In the POM The code generator dependency of general Mapper and the maven plug-in are added in the XML file. The code generator can be executed by the maven plug-in to generate the code. The code generator can also be run by using Java code or command line, and will not be described here.

<dependency>
    <groupId>tk.mybatis</groupId>
    <artifactId>mapper-generator</artifactId>
    <version>1.0.0</version>
</dependency>
copy

Add generatorConfig.xml in the resources directory

<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
    <properties resource="db.properties"/>

    <context id="Mysql" targetRuntime="MyBatis3Simple" defaultModelType="flat">
        <property name="beginningDelimiter" value="`"/>
        <property name="endingDelimiter" value="`"/>

        <!--currency Mapper of MBG plug-in unit-->
        <plugin type="tk.mybatis.mapper.generator.MapperPlugin">
            <property name="mappers" value="tk.mybatis.mapper.common.Mapper"/>
            <property name="caseSensitive" value="true"/>
        </plugin>

        <jdbcConnection driverClass="${jdbc_driver}"
                        connectionURL="${jdbc_url}"
                        userId="${jdbc_username}"
                        password="${jdbc_password}">
        </jdbcConnection>

        <javaModelGenerator targetPackage="com.citi.entity"
                            targetProject="./src/main/java"/>

        <sqlMapGenerator targetPackage="mappers"
                         targetProject="./src/main/resources"/>

        <javaClientGenerator targetPackage="com.citi.mapper"
                             targetProject="./src/main/java"
                             type="XMLMAPPER"/>
        <!--tableName="%"Indicates that all tables are involved in reverse engineering-->
        <table tableName="t_teacher" domainObjectName="Teacher">
            <generatedKey column="id" sqlStatement="Mysql"/>
        </table>

    </context>
</generatorConfiguration>
copy

Add plug-ins in pom.xml

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <encoding>UTF-8</encoding>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-maven-plugin</artifactId>
            <version>1.3.7</version>
            <configuration>
                <configurationFile>
                    ${basedir}/src/main/resources/generatorConfig.xml
                </configurationFile>
                <overwrite>true</overwrite>
                <verbose>true</verbose>
            </configuration>
            <dependencies>
                <dependency>
                    <groupId>mysql</groupId>
                    <artifactId>mysql-connector-java</artifactId>
                    <version>8.0.16</version>
                </dependency>
                <dependency>
                    <groupId>tk.mybatis</groupId>
                    <artifactId>mapper</artifactId>
                    <version>4.0.0</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>
copy

MBG running general Mapper

Code generator runs successfully

5.3 test the code generated by general Mapper

Create a new test class for TeacherMapper generated by the code generator

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:application.xml")
public class TeacherMapperTest {

    @Resource
    private TeacherMapper teacherMapper;

    @Test
    public void selectAll(){
        List<Teacher> teachers = teacherMapper.selectAll();
        for (Teacher teacher : teachers) {
            System.out.println("The content queried is::" + teacher.getTeacherName());
        }
    }

}
copy

Perform the test

The console successfully outputs the query content, and the code generated by reverse engineering of general Mapper is verified successfully.

Posted by ukscotth on Fri, 19 Aug 2022 13:49:45 +0530