1, Pure Mybatis is integrated with Mybatis plus.
1. Import dependency
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>cn.itcast.mp</artifactId> <packaging>pom</packaging> <version>1.0-SNAPSHOT</version> <modules> <module>itcast-mybatis-plus-simple</module> <module>itcast-mabatis-plus-spring</module> </modules> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <dependencies> <!-- mybatis-plus Plug in dependency --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus</artifactId> <version>3.1.1</version> </dependency> <!-- MySql --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.25</version> </dependency> <!-- Connection pool --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.24</version> </dependency> <!--simplify bean Code Toolkit--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> <version>1.18.4</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.6.4</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>
2. Create a profile
log4j.properties:
log4j.rootLogger=DEBUG,A1 log4j.appender.A1=org.apache.log4j.ConsoleAppender log4j.appender.A1.layout=org.apache.log4j.PatternLayout log4j.appender.A1.layout.ConversionPattern=[%t] [%c]-[%p] %m%n
jdbc.properties:
jdbc.username= jdbc.password= jdbc.url=jdbc:mysql://localhost:3306/mabatis-puls jdbc.driverClassName=com.mysql.jdbc.Driver jdbc.initialSize=5 jdbc.maxActive=10
3. Write mybatis config XML file:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <!-- Load external files--> <properties resource="jdbc.properties"></properties> <!-- Data source environment--> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"></transactionManager> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driverClassName}"></property> <property name="url" value="${jdbc.url}"></property> <property name="username" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </dataSource> </environment> </environments> <mappers> <mapper resource="UserMapper.xml"></mapper> </mappers> </configuration>
4. Write User entity object: (lombok is used for evolutionary bean operation here)
import com.baomidou.mybatisplus.annotation.TableName; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; /* Using lombok * @Data : Annotation on class; It provides getting and setting methods for all attributes of the class, as well as equals, canEqual, hashCode and toString methods @Setter: Annotation on attributes; Provide a setting method for the property @Getter: Annotation on attributes; Providing a getting method for a property @Log4j : Annotation on class; Provide a log4j log object with the attribute log for the class @NoArgsConstructor: Annotation on class; Provide a parameterless constructor for the class @AllArgsConstructor: Annotation on class; Provide a full parameter constructor for the class * Specify the @ User table name in the database */ @Data @NoArgsConstructor @AllArgsConstructor @TableName("tb_user") public class User { private Long id; private String user_name; private String password; private String name; private Integer age; private String email; @Override public String toString() { return "User{" + "id=" + id + ", userName='" + user_name + '\'' + ", password='" + password + '\'' + ", name='" + name + '\'' + ", age=" + age + ", email='" + email + '\'' + '}'; } }
5. Inherit UserMapper from BaseMapper and have all the methods in BaseMapper:
import cn.itcast.mp.pojo.User; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import java.util.List; public interface UserMapper extends BaseMapper<User> { public List<User> findAll(); }
6. Use the MybatisSqlSessionFactoryBuilder process in MP to build
import cn.itcast.mp.mapper.UserMapper; import cn.itcast.mp.pojo.User; import com.baomidou.mybatisplus.core.MybatisSqlSessionFactoryBuilder; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.junit.Test; import java.io.IOException; import java.io.InputStream; import java.util.List; public class MybatistTest { @Test public void testFindAll() throws IOException { InputStream resourceAsFile = Resources.getResourceAsStream("mybatis-config.xml"); //The MybatisSqlSessionFactoryBuilder in MP is used here SqlSessionFactory sqlSessionFactory = new MybatisSqlSessionFactoryBuilder().build(resourceAsFile); SqlSession sqlSession = sqlSessionFactory.openSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); // You can call the methods defined in BaseMapper List<User> users = mapper.selectList(null); System.out.println(users); sqlSession.close(); } }
Note:
① In case of operation error:
Solution: add @ TableName to the User object and specify the database table name
2, Spring + Mybatis + MP
The Spring framework is introduced, and the data source and construction are left to Spring management.
1. Import dependency
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>cn.itcast.mp</artifactId> <packaging>pom</packaging> <version>1.0-SNAPSHOT</version> <modules> <module>itcast-mybatis-plus-simple</module> <module>itcast-mabatis-plus-spring</module> </modules> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <dependencies> <!-- mybatis-plus Plug in dependency --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus</artifactId> <version>3.1.1</version> </dependency> <!-- MySql --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.25</version> </dependency> <!-- Connection pool --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.24</version> </dependency> <!--simplify bean Code Toolkit--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> <version>1.18.4</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.6.4</version> </dependency> <!--Spring Relevant coordinates--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.0.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.0.5.RELEASE</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>
2. Write JDBC properties
log4j.rootLogger=DEBUG,A1 log4j.appender.A1=org.apache.log4j.ConsoleAppender log4j.appender.A1.layout=org.apache.log4j.PatternLayout log4j.appender.A1.layout.ConversionPattern=[%t] [%c]-[%p] %m%n
3. Write ApplicationContext xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- Sweep bag--> <context:property-placeholder location="classpath:jdbc.properties"/> <!-- Define data source --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close"> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> <property name="driverClassName" value="${jdbc.driverClassName}"/> <property name="maxActive" value="10"/> <property name="minIdle" value="5"/> </bean> <!--Use here MP Provided sessionFactory complete MP and Spring Integration of--> <bean id="sessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> </bean> <!--scanning mapper Interface, still using Mybatis Native scanner--> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="mapper"/> </bean> </beans>
4. Write User object and UserMapper interface:
package pojo; import com.baomidou.mybatisplus.annotation.TableName; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @NoArgsConstructor @AllArgsConstructor @TableName("tb_user") public class User { private Long id; private String user_name; private String password; private String name; private Integer age; private String email; }
package mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import pojo.User; /** * @Description: // Class description * @ClassName: UserMapper // Class name * @Author: Zeng Weihong / / creator * @Date: 2022/1/30 11:59 // time * @Version: 1.0 // edition */ public interface UserMapper extends BaseMapper<User> { }
5. Test
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:applicationContext.xml") public class TestSpringMP { @Autowired private UserMapper userMapper; @Test public void testSelectList(){ List<User> users = this.userMapper.selectList(null); for (User user : users) { System.out.println(user); } } }
3, SpringBoot + Mybatis + MP
Using SpringBoot will further simplify MP integration. It should be noted that using SpringBoot needs to inherit the parent.
1. Import dependency
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.4.RELEASE</version> </parent> <groupId>cn.itcast.mp</groupId> <artifactId>itcast-mp-springboot</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!--Toolkit to simplify code--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!--mybatis-plus of springboot support--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.1.1</version> </dependency> <!--mysql drive--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.25</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
2. Prepare configuration file
log4j.properties:
log4j.rootLogger=DEBUG,A1 log4j.appender.A1=org.apache.log4j.ConsoleAppender log4j.appender.A1.layout=org.apache.log4j.PatternLayout log4j.appender.A1.layout.ConversionPattern=[%t] [%c]-[%p] %m%n
3. Write application properties
spring.application.name = itcast-mp-springboot spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://127.0.0.1:3306/mp? useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&useSSL=false spring.datasource.username=root spring.datasource.password=Zwh1174946082!
4. Prepare pojo
import com.baomidou.mybatisplus.annotation.TableName; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @NoArgsConstructor @AllArgsConstructor @TableName("tb_user") public class User { private Long id; private String userName; private String password; private String name; private Integer age; private String email; }
5. Write mapper
import cn.itcast.mp.pojo.User; import com.baomidou.mybatisplus.core.mapper.BaseMapper; public interface UserMapper extends BaseMapper<User> { }
6. Write startup class
package cn.itcast.mp; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.WebApplicationType; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; @MapperScan("cn.itcast.mp.mapper") //Set the scanning package of mapper interface @SpringBootApplication public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } }
7. Write test
import cn.itcast.mp.mapper.UserMapper; import cn.itcast.mp.pojo.User; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.List; @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest { @Autowired private UserMapper userMapper; @Test public void testSelect() { List<User> userList = userMapper.selectList(null); for (User user : userList) { System.out.println(user); } } }
4, Detailed explanation of general CRUD
1) Annotation details
1. Set the generation strategy of id - @ TableId details
@TableId , is the generation policy for setting id
① AUTO --- self increment of database ID
② NONE --- this type is not set with primary key
③ INPUT --- user INPUT ID * * * * this type can be filled through self registered automatic filling plug-in*****
The following three types are automatically filled only when the inserted object ID is empty.
①ID_WORKER --- globally unique ID (idWorker)
② UUID --- globally unique ID (UUID)
③ID_WORKER_STR --- globally unique ID of string (string representation of idworker)
For example:
2.@TableField
In MP, some attributes of the field can be specified through @ TableField annotation. There are three common problems to be solved:
1. Inconsistency between attribute name and field name in object (non hump)
2. The attribute field in the object does not exist in the table
3. You do not want an attribute value to appear in the query result
2) Add, delete, modify and query
1. Insert operation
Test case:
import cn.itcast.mp.mapper.UserMapper; import cn.itcast.mp.pojo.User; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.List; @RunWith(SpringRunner.class) @SpringBootTest public class TestUserMapper { @Autowired private UserMapper userMapper; @Test public void testInsert() { User user = new User(); user.setMail("2@itcast.cn"); user.setAge(301); user.setUserName("caocao1"); user.setName("Cao Cao 1"); user.setPassword("123456"); user.setAddress("Beijing"); int result = this.userMapper.insert(user); //result the number of rows affected by the database System.out.println("result => " + result); //Get the id value after self growth, and the id value after self growth will be backfilled into the user object System.out.println("id => " + user.getId()); }
2. Update operation
① Update by id
Method definition:
/** * Modify according to ID * * @param entity Entity object */ int updateById(@Param(Constants.ENTITY) T entity);
Mapped SQL statement: UPDATE tb_user SET age=? WHERE id=?
@RunWith(SpringRunner.class) @SpringBootTest public class TestUserMapper { @Autowired private UserMapper userMapper; @Test public void testUpdateById() { User user = new User(); user.setId(1L); //Condition, updated by id user.setAge(19); //Updated fields user.setPassword("666666"); int result = this.userMapper.updateById(user); System.out.println("result => " + result); } }
② Update according to conditions
Method definition:
/** * Update the record according to the whereEntity condition * * @param entity Entity object (set condition value, nullable) * @param updateWrapper Entity object encapsulates operation class (null able, and entity in it is used to generate where statement) */ int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper);
Mapped SQL statement: UPDATE tb_user SET age=? WHERE id = ?
import cn.itcast.mp.mapper.UserMapper; import cn.itcast.mp.pojo.User; import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import net.minidev.json.writer.UpdaterMapper; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.List; @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest { @Autowired private UserMapper userMapper; //Update via QueryWrapper @Test public void testUpdate() { User user = new User(); user.setAge(20); //Updated fields user.setPassword("8888888"); //update criteria QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.eq("user_name", "zhangsan"); //Match user_ Name = user data of Zhangsan //Update according to conditions int result = this.userMapper.update(user, wrapper); System.out.println("result => " + result); } //Alternatively, update through UpdateWrapper @Test public void testUpdate2() { UpdateWrapper<User> wrapper = new UpdateWrapper<>(); wrapper.set("age", 21).set("password", "999999") //For the updated field, the name of the field is set instead of the attribute of the entity .eq("user_name", "zhangsan"); //Updated conditions //Update according to conditions int result = this.userMapper.update(null, wrapper); System.out.println("result => " + result); } }
3. Delete
① Delete by id -- deleteById
Method definition:
/** * Delete by ID * * @param id Primary key ID */ int deleteById(Serializable id);
Mapped SQL statement: DELETE FROM tb_user WHERE id=?
import cn.itcast.mp.mapper.UserMapper; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest { @Autowired private UserMapper userMapper; @Test public void testDeleteById(){ // Delete data according to id int result = this.userMapper.deleteById(9L); System.out.println("result => " + result); } }
② Batch delete data according to id -- deleteBatchIds
Method definition:
/** * Delete (batch delete according to ID) * * @param idList List of primary key ID S (cannot be null and empty) */ int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
Mapped SQL statement: DELETE FROM tb_user WHERE id IN ( ? , ? , ? )
import cn.itcast.mp.mapper.UserMapper; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.Arrays; @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest { @Autowired private UserMapper userMapper; @Test public void testDeleteBatchIds(){ // Delete data in batch according to id int result = this.userMapper.deleteBatchIds(Arrays.asList(10L, 11L)); System.out.println("result => " + result); }
③ Delete by map -- deleteByMap
Method definition:
/** * Delete the record according to the columnMap condition * * @param columnMap Table field map object */ int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
Mapped SQL statement: DELETE FROM tb_user WHERE name = ? AND age = ?
import cn.itcast.mp.mapper.UserMapper; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.HashMap; import java.util.Map; @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest { @Autowired private UserMapper userMapper; @Test public void testDeleteByMap(){ Map<String,Object> map = new HashMap<>(); map.put("user_name", "zhangsan"); map.put("password", "999999"); // Delete the data according to the map, and the relationship between multiple conditions is and int result = this.userMapper.deleteByMap(map); System.out.println("result => " + result); }
④ Encapsulating conditional deletion through entity object -- delete
Method definition:
/** * Delete the record according to the entity condition * * @param wrapper Entity object encapsulates operation class (null able) */ int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
Mapped SQL statement: DELETE FROM tb_user WHERE name=? AND age=?
import cn.itcast.mp.mapper.UserMapper; import cn.itcast.mp.pojo.User; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.HashMap; import java.util.Map; @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest { @Autowired private UserMapper userMapper; @Test public void testDelete(){ //Usage 1: // QueryWrapper<User> wrapper = new QueryWrapper<>(); // wrapper.eq("user_name", "caocao1") // .eq("password", "123456"); //Usage 2 (recommended): User user = new User(); user.setPassword("123456"); user.setUserName("caocao"); QueryWrapper<User> wrapper = new QueryWrapper<>(user); // Delete according to packaging conditions int result = this.userMapper.delete(wrapper); System.out.println("result => " + result); }
4. Query operation
MP provides a variety of query operations, including query by id, batch query, query of single data, query list, paging query and so on.
① Query by id -- selectById
Method definition:
/** * Query by ID * * @param id Primary key ID */ T selectById(Serializable id);
Mapped SQL statement:
SELECT id,user_name,password,name,age,email FROM tb_user WHERE id=?
import cn.itcast.mp.mapper.UserMapper; import cn.itcast.mp.pojo.User; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest { @Autowired private UserMapper userMapper; @Test public void testSelectById() { //Query data by id User user = this.userMapper.selectById(2L); System.out.println("result = " + user); } }
② Batch query data by id - selectBatchIds()
Method definition:
/** * Query (batch query by ID) * * @param idList List of primary key ID S (cannot be null and empty) */ List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
Mapped SQL statement:
SELECT id,user_name,password,name,age,email FROM tb_user WHERE id IN ( ? , ? , ? )
import cn.itcast.mp.mapper.UserMapper; import cn.itcast.mp.pojo.User; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.Arrays; import java.util.List; @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest { @Autowired private UserMapper userMapper; @Test public void testSelectBatchIds(){ // Batch query data according to id List<User> users = this.userMapper.selectBatchIds(Arrays.asList(2L, 3L, 4L, 100L)); for (User user : users) { System.out.println(user); } } }
③ Query and return a piece of data according to the query criteria (there is only one piece of data in the query result, and an error will be reported if multiple pieces are found) --- selectOne()
Method definition:
/** * Query a record according to the entity condition * * @param queryWrapper Entity object encapsulates operation class (null able) */ T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
Mapped SQL statement:
SELECT id,user_name,password,name,age,email FROM tb_user WHERE name = ?
import cn.itcast.mp.mapper.UserMapper; import cn.itcast.mp.pojo.User; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest { @Autowired private UserMapper userMapper; @Test public void testSelectOne(){ QueryWrapper<User> wrapper = new QueryWrapper<>(); //query criteria wrapper.eq("password", "123456"); // When more than one piece of data is queried, an exception will be thrown User user = this.userMapper.selectOne(wrapper); System.out.println(user); } }
④ Total number of data pieces queried according to criteria - selectCount()
Method definition:
/** * Query the total number of records according to Wrapper conditions * * @param queryWrapper Entity object encapsulates operation class (null able) */ Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
Mapped SQL statement:
SELECT COUNT( 1 ) FROM tb_user WHERE age > ?
import cn.itcast.mp.mapper.UserMapper; import cn.itcast.mp.pojo.User; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest { @Autowired private UserMapper userMapper; @Test public void testSelectCount(){ QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.gt("age", 20); // Conditions: users over 20 years old // Query the number of data according to criteria Integer count = this.userMapper.selectCount(wrapper); System.out.println("count => " + count); } }
⑤ Query and return the list of all records according to the criteria ----- selectList()
Method definition:
/** * Query all records according to the entity condition * * @param queryWrapper Entity object encapsulates operation class (null able) */ List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
Mapped SQL statement:
SELECT id,user_name,password,name,age,email FROM tb_user WHERE age > ?
import cn.itcast.mp.mapper.UserMapper; import cn.itcast.mp.pojo.User; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.List; @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest { @Autowired private UserMapper userMapper; @Test public void testSelectList(){ QueryWrapper<User> wrapper = new QueryWrapper<>(); //Set query criteria wrapper.like("email", "itcast"); List<User> users = this.userMapper.selectList(wrapper); for (User user : users) { System.out.println(user); } } }
⑥ Query and return all data according to conditions (and turn pages) --- selectPage()
Method definition:
/** * Query all records (and turn the page) according to the entity condition * * @param page Paging query criteria (can be rowboundaries. Default) * @param queryWrapper Entity object encapsulates operation class (null able) */ IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
Mapped SQL statement:
SELECT COUNT(1) FROM tb_user WHERE age > ?
SELECT id,user_name,password,name,age,email FROM tb_user WHERE age > ? LIMIT ?,?
To configure the paging plug-in:
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; import org.mybatis.spring.annotation.MapperScan; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration @MapperScan("cn.itcast.mp.mapper") //Set the scanning package of mapper interface public class MybatisPlusConfig { /** * Paging plug-in */ @Bean public PaginationInterceptor paginationInterceptor() { return new PaginationInterceptor(); } }
import cn.itcast.mp.mapper.UserMapper; import cn.itcast.mp.pojo.User; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.List; @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest { @Autowired private UserMapper userMapper; // Test paging query @Test public void testSelectPage(){ Page<User> page = new Page<>(3,1); //Query the first page, query 1 piece of data QueryWrapper<User> wrapper = new QueryWrapper<>(); //Set query criteria wrapper.like("email", "itcast"); IPage<User> iPage = this.userMapper.selectPage(page, wrapper); System.out.println("Total number of data: " + iPage.getTotal()); System.out.println("Total data pages: " + iPage.getPages()); System.out.println("Current pages: " + iPage.getCurrent()); List<User> records = iPage.getRecords(); for (User record : records) { System.out.println(record); } }
5, Principle of SQL injection
In MP, ISqlInjector is responsible for SQL injection. It is an interface and AbstractSqlInjector is its implementation class. The implementation relationship is as follows:
AbstractSqlInjector is mainly injected by the inspectInject() method, as follows:
@Override public void inspectInject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass) { Class<?> modelClass = extractModelClass(mapperClass); if (modelClass != null) { String className = mapperClass.toString(); Set<String> mapperRegistryCache = GlobalConfigUtils.getMapperRegistryCache(builderAssistant.getConfiguration()); if (!mapperRegistryCache.contains(className)) { List<AbstractMethod> methodList = this.getMethodList(); if (CollectionUtils.isNotEmpty(methodList)) { TableInfo tableInfo = TableInfoHelper.initTableInfo(builderAssistant, modelClass); // Loop injection custom method methodList.forEach(m -> m.inject(builderAssistant, mapperClass,modelClass, tableInfo)); } else { logger.debug(mapperClass.toString() + ", No effective injection method was found."); } mapperRegistryCache.add(className); } } }
In the implementation method, methodlist forEach(m -> m.inject(builderAssistant, mapperClass, modelClass, tableInfo)); Is the key, loop traversal method, injection.
Finally, the abstract method injectMappedStatement is called for real injection:
/** * Custom injected MappedStatement * * @param mapperClass mapper Interface * @param modelClass mapper generic paradigm * @param tableInfo Database table reflection information * @return MappedStatement */ public abstract MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo);
View the implementation of this method:
Take SelectById as an example:
public class SelectById extends AbstractMethod { @Override public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) { SqlMethod sqlMethod = SqlMethod.LOGIC_SELECT_BY_ID; SqlSource sqlSource = new RawSqlSource(configuration, String.format(sqlMethod.getSql(), sqlSelectColumns(tableInfo, false), tableInfo.getTableName(), tableInfo.getKeyColumn(),tableInfo.getKeyProperty(), tableInfo.getLogicDeleteSql(true, false)), Object.class); return this.addSelectMappedStatement(mapperClass, sqlMethod.getMethod(),sqlSource, modelClass, tableInfo); } }
You can see that the SqlSource object is generated, and then the SQL is added to the meppedStatements through the addSelectMappedStatement method.
6, Disposition
1) Basic configuration
1.configLocation ---- the location of the name configuration file
MyBatis Configuration file location. If you have a separate MyBatis Configuration, please configure its path to configLocation. For details of MyBatis Configuration, please refer to the official documents of MyBatis.
Spring Boot:
mybatis-plus.config-location = classpath:mybatis-config.xml
Spring MVC:
<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean"> <property name="configLocation" value="classpath:mybatis-config.xml"/> </bean>
2. Maperlocations ---- the location of configuring custom methods
The XML file location corresponding to MyBatis Mapper. If you have a custom method in Mapper (there is a custom implementation in XML), you need to configure it and tell Mapper the corresponding XML file location.
Spring Boot:
mybatis-plus.mapper-locations = classpath*:mybatis/*.xml
The scanning path of Maven multi module project should start with classpath *: (that is, load XML files under multiple jar packages)
Spring MVC:
<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean"> <property name="mapperLocations" value="classpath*:mybatis/*.xml"/> </bean>
3.typeAliasesPackage --- configure the alias package scanning path. After configuration, you can directly use the class name
MyBaits alias package scan path, through this attribute can be registered to the class in the package alias, after registration in the Mapper corresponding XML file can use the class name directly, instead of using the fully qualified class name (that is, when XML calls do not include the package name).
Spring Boot:
mybatis-plus.type-aliases-package = cn.itcast.mp.pojo
Spring MVC:
<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean"> <property name="typeAliasesPackage" value="com.baomidou.mybatisplus.samples.quickstart.entity"/> </bean>
2) Advanced configuration
The Configuration in this section is mostly the Configuration supported by MyBatis natively, which means that you can configure it in the form of MyBatis XML Configuration file.
1.mapUnderscoreToCamelCase ---- configure whether to enable automatic hump naming rule mapping
- Type: boolean
- Default value: true
Whether to enable automatic hump naming rule (camel case) mapping, that is, from the classic database column name a_ A similar mapping from column (named by underscore) to the classic Java attribute name aColumn (named by hump).
Note: the default value of this attribute in MyBatis is false. In MyBatis plus, this attribute will also be used to generate the select body of the final SQL. If your database name complies with the rules, you do not need to specify the database field name with the @ TableField annotation.
SpringBoot:
#Turn off automatic hump mapping. This parameter cannot be compared with mybatis plus Config location exists at the same time mybatis-plus.configuration.map-underscore-to-camel-case=false
2.cacheEnabled ---- configure whether caching is required
- Type: boolean
- Default value: true
Globally turn on or off any cache that has been configured by all mappers in the configuration file. The default is true.
SpringBoot:
mybatis-plus.configuration.cache-enabled=false
3) DB policy configuration
1.idType ---- configure primary key type
- Type: com baomidou. mybatisplus. annotation. IdType
- Default: ID_WORKER
The global default primary key type. After setting, the @ TableId(type = IdType.AUTO) configuration in the entity object can be omitted.
SpringBoot:
mybatis-plus.global-config.db-config.id-type=auto
SpringMVC:
<!--Use here MP Provided sqlSessionFactory,It's done Spring And MP Integration of--> <bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="globalConfig"> <bean class="com.baomidou.mybatisplus.core.config.GlobalConfig"> <property name="dbConfig"> <bean class="com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig"> <property name="idType" value="AUTO"/> </bean> </property> </bean> </property> </bean>
3.tablePrefix----
- Type: String
- Default: null
Table name prefix. The @ TableName() configuration can be omitted after global configuration.
SpringBoot:
mybatis-plus.global-config.db-config.table-prefix=tb_
SpringMVC:
<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="globalConfig"> <bean class="com.baomidou.mybatisplus.core.config.GlobalConfig"> <property name="dbConfig"> <bean class="com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig"> <property name="idType" value="AUTO"/> <property name="tablePrefix" value="tb_"/> </bean> </property> </bean> </property> </bean>
7, Conditional constructor
In MP, the implementation class relationship of Wrapper interface is as follows:
Note: the parent classes of QueryWrapper(LambdaQueryWrapper) and UpdateWrapper(LambdaUpdateWrapper) are used to generate the where conditions of sql, and the entity attribute is also used to generate the where conditions of sql. Note: the where conditions generated by entity have no associated behavior with the where conditions generated by using various APIs.
1) allEq
① Explain
- allEq(Map params)
- allEq(Map params, boolean null2IsNull)
- allEq(boolean condition, Map params, boolean null2IsNull)
Individual parameter description: params: key is the database field name, value is the field value null2IsNull: if it is true, the isNull method will be called when the value of the map is null, and if it is false, the value with null will be ignored
- Example 1: allEq({id:1,name: "Lao Wang", age: null}) -- > id = 1 and name = 'Lao Wang' and age is null
- Example 2: allEq({id:1,name: "Lao Wang", age: null}, false) -- > id = 1 and name = 'Lao Wang'
- allEq(BiPredicate filter, Map params)
- allEq(BiPredicate filter, Map params, boolean null2IsNull)
- allEq(boolean condition, BiPredicate filter, Map params, boolean null2IsNull)
Description of individual parameters: filter: filter function, whether to allow fields to pass in params and null2IsNull in comparison conditions: the same as above
Example 1: alleq ((k, V) - > k.indexof ("a") > 0, {ID: 1, name: "Lao Wang", age: null}) - > name = 'Lao Wang' and age is null
Example 2: alleq ((k, V) - > k.indexof ("a") > 0, {ID: 1, name: "Lao Wang", age: null}, false) - > name = 'Lao Wang'
Test:
import cn.itcast.mp.mapper.UserMapper; import cn.itcast.mp.pojo.User; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.HashMap; import java.util.List; import java.util.Map; @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest { @Autowired private UserMapper userMapper; @Test public void testWrapper() { QueryWrapper<User> wrapper = new QueryWrapper<>(); //Set conditions Map<String,Object> params = new HashMap<>(); params.put("name", "Cao Cao"); params.put("age", "20"); params.put("password", null); // wrapper.allEq(params);//SELECT * FROM tb_user WHERE password IS NULL AND name = ? AND age = ? // wrapper.allEq(params,false); //SELECT * FROM tb_user WHERE name = ? AND age = ? // wrapper.allEq((k, v) -> (k.equals("name") || k.equals("age")) ,params);//SELECT * FROM tb_user WHERE name = ? AND age = ? List<User> users = this.userMapper.selectList(wrapper); for (User user : users) { System.out.println(user); } } }
2) Basic comparison operation
- eq equals=
- ne is not equal to < >
- gt > greater than >
- ge > greater than or equal to >=
- lt < less than<
- le = less than or equal to<=
- BETWEEN , BETWEEN 1 AND 2
- NOT BETWEEN not between 1 AND 2
- In field in (value. Get (0), value get(1), ...)
- Not in field NOT IN (v0, v1,...)
import cn.itcast.mp.mapper.UserMapper; import cn.itcast.mp.pojo.User; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.List; @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest { @Autowired private UserMapper userMapper; @Test public void testEq() { QueryWrapper<User> wrapper = new QueryWrapper<>(); //SELECT id,user_name,password,name,age,email FROM tb_user WHERE password = ? AND age >= ? AND name IN (?,?,?) wrapper.eq("password", "123456").ge("age", 20).in("name", "Li Si", "Wang Wu", "Zhao Liu"); List<User> users = this.userMapper.selectList(wrapper); for (User user : users) { System.out.println(user); } } }
3) Fuzzy query
- like
- % 'LIKE value
- Example: like("name", "Wang") --- > name like '% Wang%'
- notLike
- NOT LIKE '% value%'
- Example: notLike("name", "Wang") --- > name not like '% Wang%'
- likeLeft
- LIKE '% value'
- Example: likeLeft("name", "King") --- > name like '% King'
- likeRight
- LIKE 'value%'
- Example: likereight ("name", "Wang") --- > name like 'Wang%'
import cn.itcast.mp.mapper.UserMapper; import cn.itcast.mp.pojo.User; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.List; @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest { @Autowired private UserMapper userMapper; @Test public void testWrapper() { QueryWrapper<User> wrapper = new QueryWrapper<>(); //SELECT id,user_name,password,name,age,email FROM tb_user WHERE name LIKE ? //Parameters:% 1% (String) wrapper.like("name", "Cao"); List<User> users = this.userMapper.selectList(wrapper); for (User user : users) { System.out.println(user); } } }
4) Sort
- orderBy
- Sorting: ORDER BY field
- Example: orderby (true, true, "Id", "name") --- > order by ID ASC, name ASC
- orderByAsc
- Sorting: ORDER BY field ASC
- Example: orderbyasc ("Id", "name") --- > order by ID ASC, name ASC
- orderByDesc
- Sorting: ORDER BY field DESC
- Example: orderbydesc ("Id", "name") --- > order by ID DESC, name desc
import cn.itcast.mp.mapper.UserMapper; import cn.itcast.mp.pojo.User; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.List; @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest { @Autowired private UserMapper userMapper; @Test public void testWrapper() { QueryWrapper<User> wrapper = new QueryWrapper<>(); //SELECT id,user_name,password,name,age,email FROM tb_user ORDER BY age DESC wrapper.orderByDesc("age"); List<User> users = this.userMapper.selectList(wrapper); for (User user : users) { System.out.println(user); } } }
5) Logical query
- or
- Splice OR
- Actively calling or means that the next method is not connected with and! (if or is not called, and connection is used by default.)
- and
- AND nesting
- Example: and (I - > i.eq ("name", "Li Bai") ne("status", "alive") --- > and (name = 'Li Bai' and status < > 'alive')
import cn.itcast.mp.mapper.UserMapper; import cn.itcast.mp.pojo.User; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.List; @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest { @Autowired private UserMapper userMapper; @Test public void testWrapper() { QueryWrapper<User> wrapper = new QueryWrapper<>(); //SELECT id,user_name,password,name,age,email FROM tb_user WHERE name = ? OR age = ? wrapper.eq("name","Li Si").or().eq("age", 24); List<User> users = this.userMapper.selectList(wrapper); for (User user : users) { System.out.println(user); } } }
6) select
In MP query, all fields are queried by default. If necessary, you can also specify fields through the select method.
import cn.itcast.mp.mapper.UserMapper; import cn.itcast.mp.pojo.User; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.List; @RunWith(SpringRunner.class) @SpringBootTest public class UserMapperTest { @Autowired private UserMapper userMapper; @Test public void testWrapper() { QueryWrapper<User> wrapper = new QueryWrapper<>(); //SELECT id,name,age FROM tb_user WHERE name = ? OR age = ? wrapper.eq("name", "Li Si").or().eq("age", 24).select("id", "name", "age"); List<User> users = this.userMapper.selectList(wrapper); for (User user : users) { System.out.println(user); } } }
8, ActiveRecord
ActiveRecord also belongs to the ORM (object relationship mapping) layer. It was first proposed by Rails and follows the standard ORM model: table mapping to record, record mapping to object, and field mapping to object attribute. With the naming and configuration conventions followed, the operation of the model can be quickly realized to a great extent, and it is simple and easy to understand.
The main idea of ActiveRecord is:
- Create a class for each database table, and each object instance of the class corresponds to a row of records in the database table; Generally, each Field of the table has a corresponding Field in the class;
- ActiveRecord is also responsible for persisting itself. ActiveRecord encapsulates the access to the database, namely CURD;;
- ActiveRecord is a domain model that encapsulates some business logic;
(I) start AR journey
In MP, starting AR is very simple. You only need to inherit the entity object from the Model.
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.extension.activerecord.Model; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @NoArgsConstructor @AllArgsConstructor public class User extends Model<User> { private Long id; private String userName; private String password; private String name; private Integer age; private String email; }
9, Mybatis plus plug-in
1) mybatis plug-in mechanism
MyBatis allows you to intercept calls at some point during the execution of mapped statements. By default, MyBatis allows the use of plug-ins to intercept method calls, including:
1. The executor (update, query, flushstatements, commit, rollback, gettransaction, close, isclosed) intercepts the method of the executor
2. ParameterHandler (getParameterObject, setParameters) intercepts the processing of parameters
3. ResultSetHandler (handleResultSets, handleOutputParameters) intercepts the processing of result sets
4. StatementHandler (prepare, parameterize, batch, update, query) intercepts the processing constructed by Sql syntax
We have seen some methods that can intercept the Executor interface, such as update, query, commit, rollback and other methods, as well as some methods of other interfaces.
The general summary is as follows:
1. Method of intercepting actuator
2. Processing of interception parameters
3. Processing of interception result set
4. Processing of intercepting Sql syntax construction
Interceptor example:
package cn.itcast.mp.plugins; import org.apache.ibatis.executor.Executor; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.plugin.*; import java.util.Properties; @Intercepts({@Signature( type= Executor.class, method = "update", args = {MappedStatement.class,Object.class})}) public class MyInterceptor implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable { //Interception method, location of specific business logic writing return invocation.proceed(); } @Override public Object plugin(Object target) { //Create a proxy object for the target object to add the current interceptor to the object return Plugin.wrap(target, this); } @Override public void setProperties(Properties properties) { //Property settings } }
Inject into Spring container:
/** * custom interceptor */ @Bean public MyInterceptor myInterceptor(){ return new MyInterceptor(); }
2) Execute analysis plug-in
The MP provides a plug-in for SQL analysis, which can be used to block the update and deletion of the whole table,
Note: this plug-in is only applicable to the development environment, not the production environment.
SpringBoot configuration:
@Bean public SqlExplainInterceptor sqlExplainInterceptor(){ SqlExplainInterceptor sqlExplainInterceptor = new SqlExplainInterceptor(); List<ISqlParser> sqlParserList = new ArrayList<>(); // Attack SQL, block parser and join parsing chain sqlParserList.add(new BlockAttackSqlParser()); sqlExplainInterceptor.setSqlParserList(sqlParserList); return sqlExplainInterceptor; }
3) Performance analysis plug-in
The execution time of each statement will exceed the maximum execution time of the interceptor, which can be used to analyze the performance of each statement.
This plug-in is only used in the development environment and is not recommended for the production environment.
to configure:
<configuration> <plugins> <!-- Performance analysis plug-in --> <!-- SQL Perform performance analysis and use the development environment, which is not recommended online. maxTime refer to sql Maximum execution time --> <plugin interceptor="com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor"> <!--Maximum execution time in milliseconds--> <property name="maxTime" value="100"/> <!--For output SQL Format, default to false--> <property name="format" value="true"/> </plugin> </configuration>
4) Optimistic lock plug-in
1. Main applicable scenarios
Intention: when you want to update a record, you want it not to be updated by others
Optimistic lock implementation method:
- When the record is fetched, the current version is obtained
- When updating, bring this version
- When updating, set version = newVersion where version = oldVersion
- If the version is incorrect, the update fails
Plug in configuration:
①spring xml:
<bean class="com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor"/>
②spring boot:
@Bean public OptimisticLockerInterceptor optimisticLockerInterceptor() { return new OptimisticLockerInterceptor(); }
Use steps:
The @ Version annotation needs to be added to the entity field.
First, add the version field to the table and set the initial value to 1:
ALTER TABLE `tb_user` ADD COLUMN `version` int(10) NULL AFTER `email`; UPDATE `tb_user` SET `version`='1';
Step 2: add the Version field for the User entity object and add the @ Version annotation:
@Version private Integer version;
Test:
@Test public void testUpdateVersion(){ User user = new User(); user.setId(2L);// query criteria User userVersion = user.selectById(); user.setAge(23); // Updated data user.setVersion(userVersion.getVersion()); // Current version information boolean result = user.updateById(); System.out.println("result => " + result); }
Special note:
- The only supported data types are: int,Integer,long,Long,Date,Timestamp,LocalDateTime
- newVersion = oldVersion + 1 under integer type
- newVersion will be written back to entity
- Only updateById(id) and update(entity, wrapper) methods are supported
- Under the update(entity, wrapper) method, the wrapper cannot be reused!!!
10, The Sql injector implements custom global operations
When we need to extend the methods in BaseMapper, we need to use the Sql injector
① Write MyBaseMapper (other mappers can inherit this Mapper, so as to realize unified extension)
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import java.util.List; public interface MyBaseMapper<T> extends BaseMapper<T> { List<T> findAll(); // Extend other methods }
Note: all other mappers should inherit from MyBaseMapper, while MyBaseMapper should inherit from BaseMapper
For example:
package cn.itcast.mp.mapper; import cn.itcast.mp.pojo.User; public interface UserMapper extends MyBaseMapper<User> { User findById(Long id); }
② Write MySQL injector
If we inherit AbstractSqlInjector directly, the methods in the original BaseMapper will fail, so we choose to inherit DefaultSqlInjector for extension.
package cn.itcast.mp.injectors; import com.baomidou.mybatisplus.core.injector.AbstractMethod; import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector; import java.util.ArrayList; import java.util.List; public class MySqlInjector extends DefaultSqlInjector { @Override public List<AbstractMethod> getMethodList() { List<AbstractMethod> list = new ArrayList<>(); // Gets the collection in the parent class list.addAll(super.getMethodList()); // Custom re extension method list.add(new FindAll()); return list; } }
③ Write FindAll
package cn.itcast.mp.injectors; import com.baomidou.mybatisplus.core.injector.AbstractMethod; import com.baomidou.mybatisplus.core.metadata.TableInfo; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.mapping.SqlSource; public class FindAll extends AbstractMethod { @Override public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) { String sql = "select * from " + tableInfo.getTableName(); SqlSource sqlSource = languageDriver.createSqlSource(configuration,sql, modelClass); return this.addSelectMappedStatement(mapperClass, "findAll", sqlSource, modelClass, tableInfo); } }
④ Register to the Spring container
/** * Inject custom SQL injector * @return */ @Bean public MySqlInjector mySqlInjector(){ return new MySqlInjector(); }
11, Auto fill function
Sometimes we may have such requirements. When inserting or updating data, we hope that some fields can be filled with data automatically, such as password, version, etc. This function is provided in MP, which can realize automatic filling.
Development steps:
① Add @ TableField annotation
@TableField(fill = FieldFill.INSERT) //Populate when inserting data private String password;
FieldFill provides a variety of mode options:
public enum FieldFill { /** * Do not process by default */ DEFAULT, /** * Fill in fields on insertion */ INSERT, /** * Fill in fields when updating */ UPDATE, /** * Fill in fields when inserting and updating */ INSERT_UPDATE }
② Write MyMetaObjectHandler
package cn.itcast.mp.handler; import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import org.apache.ibatis.reflection.MetaObject; import org.springframework.stereotype.Component; @Component public class MyMetaObjectHandler implements MetaObjectHandler { /** * Fill in when inserting data * @param metaObject */ @Override public void insertFill(MetaObject metaObject) { // Get the value of password first, and then judge. If it is empty, fill it in. If it is not empty, do not process it Object password = getFieldValByName("password", metaObject); //Fill in if the field is empty if(null == password){ setFieldValByName("password", "888888", metaObject); } } /** * Fill in when updating data * @param metaObject */ @Override public void updateFill(MetaObject metaObject) { } }
12, Logical deletion
When developing the system, sometimes when realizing the function, the deletion operation needs to realize logical deletion. The so-called logical deletion is to mark the data as deletion, rather than the real physical deletion (non DELETE operation). The status conditions need to be carried during the query to ensure that the marked data is not queried. The purpose of this is to prevent the data from being really deleted.
Development steps:
① modify table structure
TB_ The deleted field is added to the user table to indicate whether the data has been deleted. 1 means deleted and 0 means not deleted.
ALTER TABLE `tb_user` ADD COLUMN `deleted` int(1) NULL DEFAULT 0 COMMENT '1 For deleted, 0 for not deleted' AFTER `version`;
At the same time, modify the User entity, add the deleted attribute and add the @ TableLogic annotation:
@TableLogic private Integer deleted;
② Disposition
application.properties:
# Logical deleted value (default = 1) mybatis-plus.global-config.db-config.logic-delete-value=1 # Logical undeleted value (default is 0) mybatis-plus.global-config.db-config.logic-not-delete-value=0
13, General enumeration
It solves the cumbersome configuration and makes mybatis use enumeration attributes gracefully!
Development steps:
① Modify table structure
ALTER TABLE `tb_user` ADD COLUMN `sex` int(1) NULL DEFAULT 1 COMMENT '1-Male, 2-female' AFTER `deleted`;
② Define enumeration
package cn.itcast.mp.enums; import com.baomidou.mybatisplus.core.enums.IEnum; public enum SexEnum implements IEnum<Integer> { MAN(1,"male"), WOMAN(2,"female"); private int value; private String desc; SexEnum(int value, String desc) { this.value = value; this.desc = desc; } @Override public Integer getValue() { return this.value; } @Override public String toString() { return this.desc; } }
③ Disposition
# Enumerate package scans mybatis-plus.type-enums-package=cn.itcast.mp.enums
④ Modify entity
private SexEnum sex;
14, Code generator
AutoGenerator is the code generator of mybatis plus. Through AutoGenerator, you can quickly generate the code of Entity, Mapper, Mapper XML, Service, Controller and other modules, which greatly improves the development efficiency.
Development steps:
① Create project import package
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.4.RELEASE</version> </parent> <groupId>cn.itcast.mp</groupId> <artifactId>itcast-mp-generator</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!--mybatis-plus of springboot support--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.1.1</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>3.1.1</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-freemarker</artifactId> </dependency> <!--mysql drive--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
② Write code (generally applied directly)
package cn.itcast.mp.generator; import java.util.ArrayList; import java.util.List; import java.util.Scanner; import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException; import com.baomidou.mybatisplus.core.toolkit.StringPool; import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.baomidou.mybatisplus.generator.AutoGenerator; import com.baomidou.mybatisplus.generator.InjectionConfig; import com.baomidou.mybatisplus.generator.config.DataSourceConfig; import com.baomidou.mybatisplus.generator.config.FileOutConfig; import com.baomidou.mybatisplus.generator.config.GlobalConfig; import com.baomidou.mybatisplus.generator.config.PackageConfig; import com.baomidou.mybatisplus.generator.config.StrategyConfig; import com.baomidou.mybatisplus.generator.config.TemplateConfig; import com.baomidou.mybatisplus.generator.config.po.TableInfo; import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy; import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine; /** * <p> * mysql Code generator demo example * </p> */ public class MysqlGenerator { /** * <p> * Read console content * </p> */ public static String scanner(String tip) { Scanner scanner = new Scanner(System.in); StringBuilder help = new StringBuilder(); help.append("Please enter" + tip + ": "); System.out.println(help.toString()); if (scanner.hasNext()) { String ipt = scanner.next(); if (StringUtils.isNotEmpty(ipt)) { return ipt; } } throw new MybatisPlusException("Please enter the correct" + tip + "!"); } /** * RUN THIS */ public static void main(String[] args) { // Code generator AutoGenerator mpg = new AutoGenerator(); // Global configuration GlobalConfig gc = new GlobalConfig(); String projectPath = System.getProperty("user.dir"); gc.setOutputDir(projectPath + "/src/main/java"); gc.setAuthor("itcast"); gc.setOpen(false); mpg.setGlobalConfig(gc); // Data source configuration DataSourceConfig dsc = new DataSourceConfig(); dsc.setUrl("jdbc:mysql://127.0.0.1:3306/mp?useUnicode=true&useSSL=false&characterEncoding=utf8"); // dsc.setSchemaName("public"); dsc.setDriverName("com.mysql.jdbc.Driver"); dsc.setUsername("root"); dsc.setPassword("root"); mpg.setDataSource(dsc); // Package configuration PackageConfig pc = new PackageConfig(); pc.setModuleName(scanner("Module name")); pc.setParent("cn.itcast.mp.generator"); mpg.setPackageInfo(pc); // Custom configuration InjectionConfig cfg = new InjectionConfig() { @Override public void initMap() { // to do nothing } }; List<FileOutConfig> focList = new ArrayList<>(); focList.add(new FileOutConfig("/templates/mapper.xml.ftl") { @Override public String outputFile(TableInfo tableInfo) { // Custom input file name return projectPath + "/itcast-mp-generator/src/main/resources/mapper/" + pc.getModuleName() + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML; } }); cfg.setFileOutConfigList(focList); mpg.setCfg(cfg); mpg.setTemplate(new TemplateConfig().setXml(null)); // Policy configuration StrategyConfig strategy = new StrategyConfig(); strategy.setNaming(NamingStrategy.underline_to_camel); strategy.setColumnNaming(NamingStrategy.underline_to_camel); // strategy.setSuperEntityClass("com.baomidou.mybatisplus.samples.generator.common.BaseEntity"); strategy.setEntityLombokModel(true); // strategy.setSuperControllerClass("com.baomidou.mybatisplus.samples.generator.common.BaseController"); strategy.setInclude(scanner("Table name")); strategy.setSuperEntityColumns("id"); strategy.setControllerMappingHyphenStyle(true); strategy.setTablePrefix(pc.getModuleName() + "_"); mpg.setStrategy(strategy); // When selecting freemaker engine, you need to specify the following addition. Note that pom dependency must be present! mpg.setTemplateEngine(new FreemarkerTemplateEngine()); mpg.execute(); } }
③
15, MybatisX rapid development plug-in
MybatisX is a rapid development plug-in based on IDEA, which is born for efficiency.
Installation method: open IDEA, enter file - > Settings - > plugins - > Browse repositories, enter mybatisx to search and install.
Function: Java and XML call back and jump Mapper method to automatically generate XML