tk. How does mybatis extend its own generic mapper

  • 2021-09-12 01:28:08
  • OfStack

tk. mybatis extends its generic mapper

Purpose: tk. mybatis generic mapper, although easy to use, but in some sql still can not meet our needs, and we want to control deleted statements (because generic mapper provides physical deletion, sometimes we can only carry out logical deletion for some sensitive data), so we will extend our own based on the original generic mapper

1 jar introduction


     <!--  Non springboot -->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper</artifactId>
            <version>3.4.0</version>
        </dependency>

Non-springboot projects cite this package


      <!-- springboot -->
             <dependency>
                <groupId>tk.mybatis</groupId>
                <artifactId>mapper-spring-boot-starter</artifactId>
                <version>2.0.2</version>
            </dependency>

springboot project leads this package directly. This time we will develop it based on springboot. Pay attention to the version of jar package here. If the version is too low, there will be problems, which will be introduced below

2 Writing configuration classes


package com.example.configuration;
import com.example.common.mapper.commonMapper.CommonMapper;
import org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import tk.mybatis.spring.mapper.MapperScannerConfigurer;
import java.util.Properties;
@Configuration
@AutoConfigureAfter(MybatisAutoConfiguration.class)
public class MyBatisConfiguration {
    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer() {
        MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
        mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
        mapperScannerConfigurer.setBasePackage("com.example.dao.mapper");
        Properties properties = new Properties();
        properties.setProperty("mappers", CommonMapper.class.getName());
        properties.setProperty("notEmpty", "false");
        properties.setProperty("identity", "MYSQL");
        properties.setProperty("order","BEFORE");
        mapperScannerConfigurer.setProperties(properties);
        return mapperScannerConfigurer;
    }
}

There are two points to pay attention to here:

1 > CommonMapper This is our own generic mapper, which is placed under a separate package. That is to say, there is only one mapper under this package, otherwise we will have the problem of type conversion when we apply generics. (I've been struggling here for a long time.)

2 > Here we configure the scan path of custom mapper. Note springboot Project 1 Be sure to pay attention to the jar package version. If the version is too low, the definition in the configuration class is useless. I still can't scan it. This problem will appear in the version 1.2. 3 I used before, and it can be solved by changing to a higher version.

3 Integrate the general method interface into your own custom Mapper interface

Because we use mysql database, we selectively introduce 1 commonly used method when using general functions. The following is the integration of commonly used mapper classes defined by ourselves (1 infrequently used class or method class that is not mysql will be discarded here). These base classes should not be placed under the path of BasePackage, where mapper specifies explicit generic types.

1 > Provide query function Mapper:


package com.example.common.mapper.basics;
import tk.mybatis.mapper.common.Marker;
import tk.mybatis.mapper.common.base.select.*;
import tk.mybatis.mapper.common.condition.SelectByConditionMapper;
import tk.mybatis.mapper.common.condition.SelectCountByConditionMapper;
import tk.mybatis.mapper.common.example.SelectByExampleMapper;
import tk.mybatis.mapper.common.ids.SelectByIdsMapper;
/**
 * @desc  Basic query function mapper
 *
 */
public interface SelectMapper<T> extends Marker,
        SelectOneMapper<T>,
        tk.mybatis.mapper.common.base.select.SelectMapper<T>,
        SelectAllMapper<T>,
        SelectCountMapper<T>,
        SelectByPrimaryKeyMapper<T>,
        ExistsWithPrimaryKeyMapper<T>,
        SelectByIdsMapper<T>,
        SelectByConditionMapper<T>,
        SelectCountByConditionMapper<T>,
        SelectByExampleMapper<T> {
}

2 > Provide new function mapper


package com.example.common.mapper.basics;
import tk.mybatis.mapper.common.Marker;
import tk.mybatis.mapper.common.MySqlMapper;
import tk.mybatis.mapper.common.base.insert.InsertSelectiveMapper;
/**
 * @desc  Basic insertion function mapper
 */
public interface InsertMapper<T> extends Marker,
        tk.mybatis.mapper.common.base.insert.InsertMapper<T>,
        InsertSelectiveMapper<T>,
        MySqlMapper<T>{
}

3 > Provide update function mapper


package com.example.common.mapper.basics;
import tk.mybatis.mapper.common.Marker;
import tk.mybatis.mapper.common.base.update.UpdateByPrimaryKeyMapper;
import tk.mybatis.mapper.common.base.update.UpdateByPrimaryKeySelectiveMapper;
import tk.mybatis.mapper.common.condition.UpdateByConditionMapper;
import tk.mybatis.mapper.common.condition.UpdateByConditionSelectiveMapper;
import tk.mybatis.mapper.common.example.UpdateByExampleSelectiveMapper;
/**
 * @desc  Basic update function mapper
 *
 */
public interface UpdateMapper<T> extends Marker,
        UpdateByPrimaryKeyMapper<T>,
        UpdateByPrimaryKeySelectiveMapper<T>,
        UpdateByConditionMapper<T>,
        UpdateByConditionSelectiveMapper<T>,
        UpdateByExampleSelectiveMapper<T> {
}

4 > Provide delete function mapper


package com.example.common.mapper.basics;
import com.example.common.mapper.defined.DeleteShamByIdsMapper;
import tk.mybatis.mapper.common.Marker;
import tk.mybatis.mapper.common.base.delete.DeleteByPrimaryKeyMapper;
import tk.mybatis.mapper.common.condition.DeleteByConditionMapper;
import tk.mybatis.mapper.common.ids.DeleteByIdsMapper;
/**
 * @desc  Basic deletion function mapper
 *
 */
public interface DeleteMapper<T> extends Marker,
        tk.mybatis.mapper.common.base.delete.DeleteMapper<T>,
        DeleteByPrimaryKeyMapper<T>,
        DeleteByConditionMapper<T>,
        DeleteByIdsMapper<T>{
}

5 > Provides the base class CommonMapper for adding, deleting, modifying and checking


package com.example.common.mapper.commonMapper;
import com.example.common.mapper.basics.DeleteMapper;
import com.example.common.mapper.basics.InsertMapper;
import com.example.common.mapper.basics.SelectMapper;
import com.example.common.mapper.basics.UpdateMapper;
/**
 * @param <T>
 * @desc  Basic addition, deletion, modification and search function mapper
 */
public interface CommonMapper<T> extends
        DeleteMapper<T>,
        InsertMapper<T>,
        SelectMapper<T>,
        UpdateMapper<T> {
}

6 > Entity object


package com.example.dao.entity;
import lombok.Data;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;
@Table(name="user")
@Data
public class User implements Serializable {
    @Id
    private Integer id;
    private String trueName;
    private String userName;    
    private Integer isDeleted;
}

7 > Let the custom mapper inherit from CommenMapper, and you can use these statements


package com.example.dao.mapper;
import com.example.common.mapper.commonMapper.CommonMapper;
import com.example.dao.entity.User;
public interface UserMapper extends CommonMapper<User> {
}

Next, we will enhance DeleteMapper, which provides deletion method in CommonMapper, to add logical deletion statement to it

1 > Our custom Provider needs to inherit MapperTemplate and override the constructor

This is the bulk deletion in the source code


      <!-- springboot -->
             <dependency>
                <groupId>tk.mybatis</groupId>
                <artifactId>mapper-spring-boot-starter</artifactId>
                <version>2.0.2</version>
            </dependency>
0

Next, we extend IdsProvider to support batch logical deletion

1 > Create a subclass of IdsProvider


      <!-- springboot -->
             <dependency>
                <groupId>tk.mybatis</groupId>
                <artifactId>mapper-spring-boot-starter</artifactId>
                <version>2.0.2</version>
            </dependency>
1

deleteShamByIds is our method of batch logical deletion. This method is actually to reassemble sql. tk provides many classes (SqlHelper, EntityHelper) that help us assemble sql and parameters. We can use

2 > Create an DeleteShamByIdsMapper interface


      <!-- springboot -->
             <dependency>
                <groupId>tk.mybatis</groupId>
                <artifactId>mapper-spring-boot-starter</artifactId>
                <version>2.0.2</version>
            </dependency>
2

3 > Inherit our custom logical deletion interface DeleteShamByIdsMapper in DeleteMapper


package com.example.common.mapper.basics;
import com.example.common.mapper.defined.DeleteShamByIdsMapper;
import tk.mybatis.mapper.common.Marker;
import tk.mybatis.mapper.common.base.delete.DeleteByPrimaryKeyMapper;
import tk.mybatis.mapper.common.condition.DeleteByConditionMapper;
import tk.mybatis.mapper.common.ids.DeleteByIdsMapper;
/**
 * @desc  Basic deletion function mapper
 *
 */
public interface DeleteMapper<T> extends Marker,
        tk.mybatis.mapper.common.base.delete.DeleteMapper<T>,
        DeleteByPrimaryKeyMapper<T>,
        DeleteByConditionMapper<T>,
        DeleteByIdsMapper<T>,
        DeleteShamByIdsMapper<T>{
}

At this point we have defined our custom bulk logical deletion, and we can extend the generic mapper in this way.

Several pits of TK mybatis plug-in general mapper and oracle

Recently, the company has several projects with the database oracle, a period of time useless, and then decisively fell into the pit, recording several more representative.

1: With regard to batch data insertion of oracle, the sql that I automatically spliced with insertList method of TK general mapper is as follows


      <!-- springboot -->
             <dependency>
                <groupId>tk.mybatis</groupId>
                <artifactId>mapper-spring-boot-starter</artifactId>
                <version>2.0.2</version>
            </dependency>
4

At first glance, there was nothing wrong with it, and then I reported that sql did not end correctly. Because of my overconfidence in sql, I was thinking about whether it was a parameter problem, which wasted several hours. Later, I put sql together and threw it directly into the database to run, only to find that this sql really can't run in oracle. The syntax for batch insertion of oracle should be:


      <!-- springboot -->
             <dependency>
                <groupId>tk.mybatis</groupId>
                <artifactId>mapper-spring-boot-starter</artifactId>
                <version>2.0.2</version>
            </dependency>
5

A rough look at the code of TK, it seems that there is no check database driver directly started to spell sql


      <!-- springboot -->
             <dependency>
                <groupId>tk.mybatis</groupId>
                <artifactId>mapper-spring-boot-starter</artifactId>
                <version>2.0.2</version>
            </dependency>
6

However, I think this plug-in definitely has a compatible scheme, and the use of this plug-in does not conflict with the use of the source mybatis, so it actually has no impact on the development. It is regarded as reviewing the foundation of oracle and reminding myself that programmers still honestly start with run, and their self-righteous experience is sometimes very poor.

2: Comparison symbols for oracle ( < > =) and null

Review 1 time first

is null or is not null is used when a certain field is empty or not in a general database query

If the query criteria are = null or < > null can't find out the data

However, you can assign values with = null as


      <!-- springboot -->
             <dependency>
                <groupId>tk.mybatis</groupId>
                <artifactId>mapper-spring-boot-starter</artifactId>
                <version>2.0.2</version>
            </dependency>
7

This can be executed successfully, but this is a value operation outside the table, so when the data in the table has null, what pits are there, such as


select * from table1 where name <>'zhansan'

If the name field in the query table is not zhangsan, the data can not be found out when the name is null. For example, if there are 100 pieces of data in the table, the name value of 1 piece of data is zhangsan, and the name value of 9 pieces of data is null, then only 90 pieces of data can be found out in this sql. Therefore, if the exact demand is to query the data with name value not zhangsan and including the data with null value, sql should be


      <!-- springboot -->
             <dependency>
                <groupId>tk.mybatis</groupId>
                <artifactId>mapper-spring-boot-starter</artifactId>
                <version>2.0.2</version>
            </dependency>
9

3: This is a specification of mybatis, which is basically a number, but it also pits me

First: When mybatis inserts null value, you need to specify the type of the value (jdbctype), otherwise an error will be reported.

Because mybatis will adapt to the matching database field type without specifying the type, null cannot adapt. If you can't handle it, report an error, which is very stable. However, if 1 uses xml to configure sql, 1 will not have this problem, and it will be written conveniently when writing. This is also the problem exposed when I use TK. When I use insert method, null hangs up, but TK has an insertSelective method that will automatically filter out null values when inserting.


Related articles: