MyBatisPlus

6 篇文章 0 订阅

文章目录

一、MyBatisPlus概况

1. 代码及文档地址

官方地址

代码发布地址:github

代码发布地址:gitee

文档发布地址

2.前置知识

Mybatis

Spring

Maven

二、集成MP

1.创建测试表

-- 创建库
CREATE DATABASE mp;
-- 使用库
USE mp;
-- 创建表
CREATE TABLE tbl_employee(
 id INT(11) PRIMARY KEY AUTO_INCREMENT,
 last_name VARCHAR(50),
 email VARCHAR(50),
 gender CHAR(1),
 age int
);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Tom','tom@atguigu.com',1,22);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Jerry','jerry@atguigu.com',0,25);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('Black','black@atguigu.com',1,30);
INSERT INTO tbl_employee(last_name,email,gender,age) VALUES('White','white@atguigu.com',0,35);

2.创建javaBean

public class Employee {
    private Integer id ; 
    private String lastName; 
    private String email ;
    private Integer gender ;
    private Integer age ;
    
    public Integer getId() {return id; }
    public void setId(Integer id) {this.id = id; }
    
    public String getLastName() {return lastName;}
    public void setLastName(String lastName) {this.lastName = lastName; }
    
    public String getEmail() {return email; }
    public void setEmail(String email) {this.email = email; }
    
    public Integer getGender() {return gender; }
    public void setGender(Integer gender) {this.gender = gender; }
    
    public Integer getAge() {return age; }
    public void setAge(Integer age) {this.age = age; }
    
    @Override
    public String toString() {
        return "Employee [id=" + id + ", lastName=" + lastName + ", email=" + email
        + ", gender=" + gender + ", age="
        + age + "]"; 
    }
}

3.依赖配置

3.1 在pom.xml中添加依赖

加入对 MP、Spring、连接池、Junit、Mysql 驱动等依赖

<!-- mp 依赖 -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus</artifactId>
    <version>2.3</version>
</dependency>

<!--junit -->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.9</version>
</dependency>

<!-- log4j -->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

<!-- c3p0 -->
<dependency>
    <groupId>com.mchange</groupId>
    <artifactId>c3p0</artifactId>
    <version>0.9.5.2</version>
</dependency>

<!-- mysql -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.37</version>
</dependency>

<!-- spring -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>4.3.10.RELEASE</version>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-orm</artifactId>
    <version>4.3.10.RELEASE</version>
</dependency>

Mybatis 及 Mybatis-Spring 依赖请勿加入项目配置,以免引起版本冲突!!!Mybatis-Plus 会自动帮你维护!

3.2 MyBatis全局配置文件

<?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>
 </configuration>

3.3 log4j.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
    <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
         <param name="Encoding" value="UTF-8" />
         <layout class="org.apache.log4j.PatternLayout">
             <param name="ConversionPattern" value="%-5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n"/>
         </layout>
    </appender>

    <logger name="java.sql">
        <level value="debug" />
    </logger>

    <logger name="org.apache.ibatis">
        <level value="info" />
    </logger>

    <root>
         <level value="debug" />
         <appender-ref ref="STDOUT" />
    </root>
</log4j:configuration>

3.4 加入 db.properties 连接信息配置

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mp
jdbc.username=root
jdbc.password=1234

3.5 加入 spring 的配置文件 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"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
xsi:schemaLocation="http://mybatis.org/schema/mybatis-spring 
http://mybatis.org/schema/mybatis-spring-1.2.xsd
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-4.0.xsd
http://www.springframework.org/schema/tx 
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<!-- 数据源 -->
<context:property-placeholder location="classpath:db.properties"/>
<bean id="dataSource" 
class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"></property>
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="user" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!-- 事务管理器 -->
<bean id="dataSourceTransactionManager" 
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 基于注解的事务管理 -->
<tx:annotation-driven 
transaction-manager="dataSourceTransactionManager"/>
<!-- 配置 SqlSessionFactoryBean -->
<bean id="sqlSessionFactoryBean" 
class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- 数据源 -->
<property name="dataSource" ref="dataSource"></property>
<property name="configLocation"
          value="classpath:mybatis-config.xml"></property>
<!-- 别名处理 -->
<property name="typeAliasesPackage" 
value="com.atguigu.mp.beans"></property>
</bean>
<!--
配置 mybatis 扫描 mapper 接口的路径
-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" 
value="com.atguigu.mp.mapper"></property>
</bean>
</beans>

4.测试

private ApplicationContext iocContext = new ClassPathXmlApplicationContext("applicationContext.xml");

@Test
public void testEnvironment() throws Exception{
    DataSource ds = iocContext.getBean("dataSource",DataSource.class);
    Connection conn = ds.getConnection();
    System.out.println(conn);
}

5.集成MP

Mybatis-Plus 的集成非常简单,对于 Spring,我们仅仅需要把 Mybatis 自带的MybatisSqlSessionFactoryBean 替换为 MP 自带的即可。

<bean id="sqlSessionFactoryBean" class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean">
    <!-- 数据源 -->
        <property name="dataSource" ref="dataSource"></property>
        <property name="configLocation" value="classpath:mybatis-config.xml"></property>
    <!-- 别名处理 -->
    <property name="typeAliasesPackage" 
    value="com.atguigu.mp.beans"></property>
</bean>

三、入门操作

1.通用crud

  • 假设我们已存在一张 tbl_employee 表,且已有对应的实体类 Employee,实现tbl_employee 表的 CRUD 操作我们需要做什么呢?

  • 实现方式:

    • 基于 Mybatis

      需要编写 EmployeeMapper 接口,并手动编写 CRUD 方法。提供 EmployeeMapper.xml 映射文件,并手动编写每个方法对应的 SQL 语句.

    • 基于 MP

      只需要创建 EmployeeMapper 接口, 并继承 BaseMapper 接口.这就是使用 MP需要完成的所有操作,甚至不需要创建 SQL 映射文件。

2.插入操作

  • Integer insert(T entity);

    插入时会根据实体类的每个属性进行非空判断,只有非空的才会出现到SQL语句中

    //初始化Employee对象
    Employee employee  = new Employee();
    employee.setLastName("MP");
    employee.setEmail("mp@atguigu.com");
    employee.setGender(1);
    employee.setAge(22);
    employee.setSalary(20000.0);
    //插入到数据库   
    // insert方法在插入时, 会根据实体类的每个属性进行非空判断,只有非空的属性对应的字段才会出现到SQL语句中
    employeeMapper.insert(employee);  
    
  • @TableName(value=“tbl_employee”)或者全局的 MP 配置:

  • @TableField(value=“last_name”)或者全局的 MP 配置:

  • @TableId(value = “id” , type = IdType.AUTO)或者全局的 MP 配置:

  • 支持主键自增的数据库插入数据获取主键值

    • Mybatis: 需要通过 useGeneratedKeys 以及 keyProperty 来设置

    • MP: 自动将主键值回写到实体类中

  • Integer insertAllColumn(T entity)

    插入时不管属性是否为空,属性所对应的字段都会出现到SQL语句中

    //初始化Employee对象
    Employee employee  = new Employee();
    employee.setLastName("MP");
    employee.setEmail("mp@atguigu.com");
    //employee.setGender(1);
    //employee.setAge(22);
    //insertAllColumn方法在插入时, 不管属性是否非空, 属性所对应的字段都会出现到SQL语句中. 
    employeeMapper.insertAllColumn(employee);
    

3.更新操作

  • Integer updateById(@Param(“et”) T entity);

    //初始化修改对象
    Employee employee = new Employee();
    employee.setId(7);
    employee.setLastName("小泽老师");
    employee.setEmail("xz@sina.com");
    employee.setGender(0);
    employee.setAge(33);
    
    employeeMapper.updateById(employee);
    
  • Integer updateAllColumnById(@Param(“et”) T entity)

    注意:此方法若没有给某些字段赋值,则会将这些字段更新为null,若更新前原本有值,慎用此方法。

    //初始化修改对象
    Employee employee = new Employee();
    employee.setId(7);
    employee.setLastName("小泽老师");
    employee.setEmail("xz@sina.com");
    employee.setGender(0);
    //employee.setAge(33);
    
    employeeMapper.updateAllColumnById(employee);
    

4.查询操作

4.1 通过id查询

  • T selectById(Serializable id);

    //通过id查询
    Employee employee = employeeMapper.selectById(7);
    System.out.println(employee);
    

4.2 通过多个列进行查询,只能进行结果只有一条数据的查询

  • T selectOne(@Param(“ew”) T entity);

    //通过多个列进行查询    id  +  lastName  +  gender
    Employee  employee = new Employee();
    employee.setId(7);
    employee.setLastName("小泽老师");
    employee.setGender(0);
    Employee result = employeeMapper.selectOne(employee);
    System.out.println("result: " +result );
    

4.3 通过多个id查询

  • List selectBatchIds(List<? extends Serializable> idList);
//通过多个id进行查询   
List<Integer> idList = new ArrayList<>();
idList.add(4);
idList.add(5);
idList.add(6);
idList.add(7);
List<Employee> emps = employeeMapper.selectBatchIds(idList);
System.out.println(emps);

4.4 通过Map封装条件查询

  • List selectByMap(@Param(“cm”) Map<String, Object> columnMap);

    集合中要写的是数据库表的列名,不是实体类的属性名。

    //通过Map封装条件查询
    Map<String,Object> columnMap = new HashMap<>();
    columnMap.put("last_name", "Tom");
    columnMap.put("gender", 1);
    List<Employee> emps = employeeMapper.selectByMap(columnMap);
    System.out.println(emps);
    

4.5 分页查询

  • List selectPage(RowBounds rowBounds, @Param(“ew”) Wrapper wrapper);

    //5. 分页查询
    List<Employee> emps = employeeMapper.selectPage(new Page<>(3, 2), null);
    System.out.println(emps);
    

5.删除操作

5.1 根据id删除

  • Integer deleteById(Serializable id);

    //1 .根据id进行删除
    Integer result = employeeMapper.deleteById(13);
    System.out.println("result: " + result );
    

5.2 根据 条件进行删除

  • Integer deleteByMap(@Param(“cm”) Map<String, Object> columnMap);

    Map<String,Object> columnMap = new HashMap<>();
    columnMap.put("last_name", "MP");
    columnMap.put("email", "mp@atguigu.com");
    Integer result = employeeMapper.deleteByMap(columnMap);
    System.out.println("result: " + result );
    

5.3 批量删除

  • Integer deleteBatchIds(List<? extends Serializable> idList);
//批量删除
List<Integer> idList = new ArrayList<>();
idList.add(3);
idList.add(4);
idList.add(5);
Integer result = employeeMapper.deleteBatchIds(idList);
System.out.println("result: " + result );

6.启动注入 SQL 原理分析

  • 问题: xxxMapper 继承了 BaseMapper, BaseMapper 中提供了通用的 CRUD 方法,方法来源于 BaseMapper, 有方法就必须有 SQL, 因为 MyBatis 最终还是需要通过SQL 语句操作数据.

  • 前置知识:MyBatis 源码中比较重要的一些对象, MyBatis 框架的执行流程

Configuration、MappedStatement………

  • 通过现象看到本质

A. employeeMapper 的本质 org.apache.ibatis.binding.MapperProxy

B. MapperProxy 中 sqlSession –>SqlSessionFactory

C. SqlSessionFacotry 中 → Configuration→ MappedStatements

每一个 mappedStatement 都表示 Mapper 接口中的一个方法与 Mapper 映射文件中的一个 SQL。 MP 在启动就会挨个分析 xxxMapper 中的方法,并且将对应的 SQL 语句处理好,保存到 configuration 对象中的 mappedStatements 中.

D. 本质:

​ Configuration: MyBatis 或者 MP 全局配置对象

​ MappedStatement:一个 MappedStatement 对象对应 Mapper 配置文件中的一个

​ select/update/insert/delete 节点,主要描述的是一条 SQL 语句

​ SqlMethod : 枚举对象 ,MP 支持的 SQL 方法

​ TableInfo:数据库表反射信息 ,可以获取到数据库表相关的信息

​ SqlSource: SQL 语句处理对象

​ MapperBuilderAssistant: 用于缓存、SQL 参数、查询方剂结果集处理等. 通过 MapperBuilderAssistant 将每一个 mappedStatement 添加到 configuration 中的 mappedstatements 中

四、条件构造器 EntityWrapper

1.简介

  • Mybatis-Plus 通过 EntityWrapper(简称 EW,MP 封装的一个查询条件构造器)或者Condition(与 EW 类似) 来让用户自由的构建查询条件,简单便捷,没有额外的负担,能够有效提高开发效率

  • 实体包装器,主要用于处理 sql 拼接,排序,实体参数查询等

  • 注意: 使用的是数据库字段,不是 Java 属性!

  • 条件参数说明

2.案例

需求:分页查询 tbl_employee 表中,年龄在 18~50 之间性别为男且姓名为 xx 的所有用户。

实现:

List<Employee> userList = employeeMapper.selectPage(
 new Page<Employee>(2, 3),
 new EntityWrapper<Employee>()
    .eq("last_name", "MybatisPlus")
 	.eq("gender", 1)
 	.between("age", 18, 50)
);

3.带条件的查询

List selectList(@Param(“ew”) Wrapper wrapper);

//分页查询tbl_employee表中,年龄在18~50之间且性别为男且姓名为Tom的所有用户
List<Employee> emps =employeeMapper.selectPage(
    new Page<Employee>(1, 2),
	new EntityWrapper<Employee>()
		.between("age", 18, 50)
		.eq("gender", 1)
		.eq("last_name", "Tom")
);
System.out.println(emps);

// 查询tbl_employee表中, 性别为女并且名字中带有"老师" 或者  邮箱中带有"a"
List<Employee> emps = employeeMapper.selectList(
	new EntityWrapper<Employee>()
		.eq("gender", 0)
		.like("last_name", "老师")
		//.or()    // SQL: (gender = ? AND last_name LIKE ? OR email LIKE ?)    
		.orNew()   // SQL: (gender = ? AND last_name LIKE ?) OR (email LIKE ?) 
		.like("email", "a")
);
System.out.println(emps);

// 查询性别为女的, 根据age进行排序(asc/desc), 简单分页
List<Employee> emps  = employeeMapper.selectList(
	new EntityWrapper<Employee>()
		.eq("gender", 0)
		//.orderBy("age") //默认升序
		.orderDesc(Arrays.asList(new String [] {"age"}))
		.last("desc limit 1,3")
);
System.out.println(emps);

4.带条件的修改

Integer update(@Param(“et”) T entity, @Param(“ew”) Wrapper wrapper);

Employee employee = new Employee();
employee.setLastName("苍老师");
employee.setEmail("cls@sina.com");
employee.setGender(0);
		
employeeMapper.update(employee, 
	new EntityWrapper<Employee>()
		.eq("last_name", "Tom")
		.eq("age", 44)
);

5.带条件的删除

Integer delete(@Param(“ew”) Wrapper wrapper);

employeeMapper.delete(
	new EntityWrapper<Employee>()
		.eq("last_name", "Tom")
		.eq("age", 22)
);

6.使用 Condition 的方式打开如上需求

//分页查询tbl_employee表中,年龄在18~50之间且性别为男且姓名为Tom的所有用户
List<Employee > emps = employeeMapper.selectPage(
	new Page<Employee>(1,2), 
	Condition.create()
		.between("age", 18, 50)
		.eq("gender", "1")
		.eq("last_name", "Tom")
);
System.out.println(emps);	

7.小结

MP: EntityWrapper Condition 条件构造器

MyBatis MBG : xxxExample→Criteria : QBC( Query By Criteria)

​ Hibernate 、 通用 Mapper

五、ActiveRecord(活动记录)

Active Record(活动记录),是一种领域模型模式,特点是一个模型类对应关系型数据库中的一个表,而模型类的一个实例对应表中的一行记录。

ActiveRecord 一直广受动态语言( PHP 、 Ruby 等)的喜爱,而 Java 作为准静态语言,对于ActiveRecord 往往只能感叹其优雅,所以 MP 也在 AR 道路上进行了一定的探索

1.如何使用AR模式

让实体类继承 Model 类且实现主键指定方法即可

import com.baomidou.mybatisplus.activerecord.Model;

public class Employee extends Model<Employee> {
    ...
        
    /**
	 * 指定当前实体类的主键属性
	 */
	@Override
	protected Serializable pkVal() {
		return id;
	} 
    
}

2.AR基本CRUD

2.1 AR 插入操作

public boolean insert()

Employee employee = new Employee();
employee.setLastName("宋老师");
employee.setEmail("sls@atguigu.com");
employee.setGender(1);
employee.setAge(35);

boolean result = employee.insert();
System.out.println("result:" +result );

2.2 修改操作

public boolean updateById()

Employee employee = new Employee();
employee.setId(20);
employee.setLastName("宋老湿");
employee.setEmail("sls@atguigu.com");
employee.setGender(1);
employee.setAge(36);

boolean result = employee.updateById();
System.out.println("result:" +result );

2.3 查询操作

  • public T selectById()
Employee employee = new Employee();
employee.setId(14);
Employee result = employee.selectById();
System.out.println(result );
  • public T selectById(Serializable id)
Employee employee = new Employee();
Employee result = employee.selectById(14);
System.out.println(result );
  • public List selectAll()
Employee employee = new Employee();
List<Employee> emps = employee.selectAll();
System.out.println(emps);
  • public List selectList(Wrapper wrapper)
Employee employee = new Employee();
List<Employee > emps= 
employee.selectList(
    new EntityWrapper<Employee>()
    	.like("last_name", "老师")
);
System.out.println(emps);
  • public int selectCount(Wrapper wrapper)
Employee employee = new Employee();
Integer result = employee.selectCount(
    new EntityWrapper<Employee>()
    	.eq("gender", 0)
);
System.out.println("result: " +result );

2.4 删除操作

  • public boolean deleteById()
Employee employee = new Employee();
employee.setId(2);
boolean result = employee.deleteById();
System.out.println("result:" +result );
  • public boolean deleteById(Serializable id)
Employee employee = new Employee();
boolean result = employee.deleteById(2);
System.out.println("result:" +result );
  • public boolean delete(Wrapper wrapper)
Employee employee = new Employee();
boolean result = employee.delete(
    new EntityWrapper<Employee>()
    	.like("last_name", "小")
);
System.out.println(result );

2.5 分页复杂操作

  • public Page selectPage(Page page, Wrapper wrapper)
Employee employee = new Employee();	
Page<Employee> page = employee.selectPage(
    new Page<>(1, 1), 
	new EntityWrapper<Employee>()
    	.like("last_name", "老")
);
List<Employee> emps = page.getRecords();
System.out.println(emps);

3.小结

AR 模式提供了一种更加便捷的方式实现 CRUD 操作,其本质还是调用的 Mybatis 对应的方法,类似于语法糖

语法糖是指计算机语言中添加的某种语法,这种语法对原本语言的功能并没有影响.可以更方便开发者使用,可以避免出错的机会,让程序可读性更好.

六、代码生成器

  1. MP 提供了大量的自定义设置,生成的代码完全能够满足各类型的需求

  2. MP 的代码生成器 和 Mybatis MBG 代码生成器:

  • MP 的代码生成器都是基于 java 代码来生成。
  • MBG 基于 xml 文件进行代码生成
  • MyBatis 的代码生成器可生成: 实体类、Mapper 接口、Mapper 映射文件
  • MP 的代码生成器可生成: 实体类(可以选择是否支持 AR)、Mapper 接口、Mapper 映射文件、 Service 层、Controller 层.
  1. 表及字段命名策略选择

    在 MP 中,我们建议数据库表名 和 表字段名采用驼峰命名方式, 如果采用下划线命名方式。请开启全局下划线开关,如果表名字段名命名方式不一致请注解指定,我们建议最好保持一致。这么做的原因是为了避免在对应实体类时产生的性能损耗,这样字段不用做映射就能直接和实体类对应。当然如果项目里不用考虑这点性能损耗,那么你采用下滑线也是没问题的,只需要在生成代码时配置dbColumnUnderline 属性就可以

1.依赖

1.1 模板引擎

MP 的代码生成器默认使用的是 Apache 的 Velocity 模板,当然也可以更换为别的模板技术,例如 freemarker。需要加入 Apache Velocity 的依赖

<dependency>
 <groupId>org.apache.velocity</groupId>
 <artifactId>velocity-engine-core</artifactId>
 <version>2.0</version>
</dependency>

1.2 加入 slf4j ,查看日志输出信息

<dependency> 
    <groupId>org.slf4j</groupId> 
    <artifactId>slf4j-api</artifactId> 
    <version>1.7.7</version>
</dependency> 

<dependency> 
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId> 
    <version>1.7.7</version>
</dependency>

2.示例代码

@Test
public void  testGenerator() {
    //1. 全局配置
    GlobalConfig config = new GlobalConfig();
    config.setActiveRecord(true) // 是否支持AR模式
        .setAuthor("alvis-yaing") // 作者
        .setOutputDir("E:\JavaProjects\official\scantest\src\main\java") // 生成路径
        .setFileOverride(true)  // 文件覆盖
        .setIdType(IdType.AUTO) // 主键策略
        .setServiceName("%sService")  // 设置生成的service接口的名字的首字母是否为I
        // IEmployeeService
        .setBaseResultMap(true)
        .setBaseColumnList(true);

    //2. 数据源配置
    DataSourceConfig  dsConfig  = new DataSourceConfig();
    dsConfig.setDbType(DbType.MYSQL)  // 设置数据库类型
        .setDriverName("com.mysql.jdbc.Driver")
        .setUrl("jdbc:mysql://localhost:3306/mp")
        .setUsername("root")
        .setPassword("root");

    //3. 策略配置
    StrategyConfig stConfig = new StrategyConfig();
    stConfig.setCapitalMode(true) //全局大写命名
        .setDbColumnUnderline(true)  // 指定表名 字段名是否使用下划线
        .setNaming(NamingStrategy.underline_to_camel) // 数据库表映射到实体的命名策略
        .setTablePrefix("tbl_")
        .setInclude("tbl_employee");  // 生成的表

    //4. 包名策略配置 
    PackageConfig pkConfig = new PackageConfig();
    pkConfig.setParent("com.deepcre.mvc")
        .setMapper("mapper")
        .setService("service")
        .setController("controller")
        .setEntity("beans")
        .setXml("mapper");

    //5. 整合配置
    AutoGenerator  ag = new AutoGenerator();

    ag.setGlobalConfig(config)
        .setDataSource(dsConfig)
        .setStrategy(stConfig)
        .setPackageInfo(pkConfig);

    //6. 执行
    ag.execute();
}

不用再进行mapper的注入.EmployeeServiceImpl 继承了ServiceImpl

在ServiceImpl中已经完成Mapper对象的注入,直接在EmployeeServiceImpl中进行使用

在ServiceImpl中也帮我们提供了常用的CRUD方法, 基本的一些CRUD方法在Service中不需要我们自己定义.

3.小结

其他配置参考地址

七、插件扩展

1.Mybatis插件机制简介

  1. 插件机制:Mybatis 通过插件(Interceptor) 可以做到拦截四大对象相关方法的执行,根据需求,完成相关数据的动态改变。
  • Executor
  • StatementHandler
  • ParameterHandler
  • ResultSetHandler
  1. 插件原理:四大对象的每个对象在创建时,都会执行 interceptorChain.pluginAll(),会经过每个插件对象的 plugin()方法,目的是为当前的四大对象创建代理。代理对象就可以拦截到四大对象相关方法的执行,因为要执行四大对象的方法需要经过代理.

2.分页插件

com.baomidou.mybatisplus.plugins.PaginationInterceptor

插件注册(appplicationContext.xml)

<!-- mp分页插件注册 -->
<property name="plugins">
    <list>
        <!-- 注册分页插件 -->
        <bean class="com.baomidou.mybatisplus.plugins.PaginationInterceptor"></bean>
    </list>
</property>
/**
	 * 测试分页插件
	 */
@Test
public void testPage() {
    Page<Employee> page = new Page<>(1,1);

    List<Employee > emps = employeeMapper.selectPage(page, null);
    System.out.println(emps);

    System.out.println("===============获取分页相关的一些信息======================");

    System.out.println("总条数:" +page.getTotal());
    System.out.println("当前页码: "+  page.getCurrent());
    System.out.println("总页码:" + page.getPages());
    System.out.println("每页显示的条数:" + page.getSize());
    System.out.println("是否有上一页: " + page.hasPrevious());
    System.out.println("是否有下一页: " + page.hasNext());

    //将查询的结果封装到page对象中
    page.setRecords(emps);
}

3.执行分析插件

  • com.baomidou.mybatisplus.plugins.SqlExplainInterceptor
  • SQL 执行分析拦截器,只支持 MySQL5.6.3 以上版本
  • 该插件的作用是分析 DELETE UPDATE 语句,防止小白或者恶意进行 DELETE UPDATE 全表操作
  • 只建议在开发环境中使用,不建议在生产环境使用
  • 在插件的底层 通过 SQL 语句分析命令:Explain 分析当前的 SQL 语句,根据结果集中的 Extra 列来断定当前是否全表操作。

插件注册(appplicationContext.xml)

<!-- 插件注册 -->
<property name="plugins">
    <list>
        <!-- 注册执行分析插件 -->
        <bean class="com.baomidou.mybatisplus.plugins.SqlExplainInterceptor">
            <property name="stopProceed" value="true"></property>
        </bean>
    </list>
</property>
/**
	 * 测试SQL执行分析插件
	 */
@Test
public void testSQLExplain() {
    employeeMapper.delete(null);  // 全表删除
}

4.性能分析插件

  • com.baomidou.mybatisplus.plugins.PerformanceInterceptor
  • 性能分析拦截器,用于输出每条 SQL 语句及其执行时间
  • SQL 性能执行分析,开发环境使用*,*超过指定时间,停止运行。有助于发现问题

插件注册(appplicationContext.xml)

<!-- 插件注册 -->
<property name="plugins">
    <list>
        <!-- 注册性能分析插件 -->
        <bean class="com.baomidou.mybatisplus.plugins.PerformanceInterceptor">
            <property name="format" value="true"></property>
            <!-- <property name="maxTime" value="5"></property> -->
        </bean>
    </list>
</property>
/**
 * 测试 性能分析插件
 */
@Test
public void testPerformance() {
    Employee employee = new Employee();
    employee.setLastName("玛利亚老师");
    employee.setEmail("mly@sina.com");
    employee.setGender("0");
    employee.setAge(22);

    employeeMapper.insert(employee);

}

5.注册乐观锁插件

  • com.baomidou.mybatisplus.plugins.OptimisticLockerInterceptor

  • 如果想实现如下需求: 当要更新一条记录的时候,希望这条记录没有被别人更新

  • 乐观锁的实现原理:

    • 取出记录时,获取当前 version 2

    • 更新时,带上这个 version 2

    • 执行更新时, set version = yourVersion+1 where version = yourVersion

    • 如果 version 不对,就更新失败

  • @Version 用于注解实体字段,必须要有。

插件注册(appplicationContext.xml)

<!-- 插件注册 -->
<property name="plugins">
    <list>
        <!-- 注册乐观锁插件 -->
        <bean class="com.baomidou.mybatisplus.plugins.OptimisticLockerInterceptor">
        </bean>
    </list>
</property>
/**
	 * 测试 乐观锁插件
	 */
	
@Test
public void testOptimisticLocker() {
    //更新操作
    Employee employee = new Employee();
    employee.setId(15);
    employee.setLastName("TomAA");
    employee.setEmail("tomAA@sina.com");
    employee.setGender("1");
    employee.setAge(22);
    employee.setVersion(3);

    employeeMapper.updateById(employee);

}

八、自定义全局操作

根据 MybatisPlus 的 AutoSqlInjector 可以自定义各种你想要的 sql ,注入到全局中,相当于自定义 Mybatisplus 自动注入的方法。之前需要在 xml 中进行配置的 SQL 语句,现在通过扩展 AutoSqlInjector 在加载 mybatis 环境时就注入。

1.设置步骤

  1. 在 Mapper 接口中定义相关的 CRUD 方法

    int  deleteAll();
    
  2. 扩展 AutoSqlInjector inject 方法,实现 Mapper 接口中方法要注入的 SQL

    package com.atguigu.mp.injector;
    
    import org.apache.ibatis.builder.MapperBuilderAssistant;
    import org.apache.ibatis.mapping.SqlSource;
    import org.apache.ibatis.session.Configuration;
    
    import com.baomidou.mybatisplus.entity.TableInfo;
    import com.baomidou.mybatisplus.mapper.AutoSqlInjector;
    
    /**
     * 自定义全局操作
     */
    public class MySqlInjector  extends AutoSqlInjector{
    	
    	/**
    	 * 扩展inject 方法,完成自定义全局操作
    	 */
    	@Override
    	public void inject(Configuration configuration, MapperBuilderAssistant builderAssistant, Class<?> mapperClass,
    			Class<?> modelClass, TableInfo table) {
    		//将EmployeeMapper中定义的deleteAll, 处理成对应的MappedStatement对象,加入到configuration对象中。
    		
    		//注入的SQL语句
    		String sql = "delete from " +table.getTableName();
    		//注入的方法名   一定要与EmployeeMapper接口中的方法名一致
    		String method = "deleteAll" ;
    		
    		//构造SqlSource对象
    		SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
    		
    		//构造一个删除的MappedStatement
    		this.addDeleteMappedStatement(mapperClass, method, sqlSource);
    		
    	}
    }
    
    
  3. 在 MP 全局策略中,配置 自定义注入器

<!-- 定义自定义注入器 -->
<bean id="mySqlInjector" class="com.atguigu.mp.injector.MySqlInjector"></bean>

<!-- 定义MybatisPlus的全局策略配置-->
<bean id ="globalConfiguration" class="com.baomidou.mybatisplus.entity.GlobalConfiguration">
    ...

    <!--注入自定义全局操作 -->
  <property name="sqlInjector" ref="mySqlInjector"></property>
  
</bean>

2.测试代码

/**
	 * 测试自定义全局操作
	 */
@Test
public void  testMySqlInjector() {
    Integer result = employeeMapper.deleteAll();
    System.out.println("result: " +result );
}

3.自定义注入器的应用之 逻辑删除

假删除、逻辑删除: 并不会真正的从数据库中将数据删除掉,而是将当前被删除的这条数据中的一个逻辑删除字段置为删除状态.

tbl_user logic_flag = 1 → -1

  1. com.baomidou.mybatisplus.mapper.LogicSqlInjector
  2. logicDeleteValue 逻辑删除全局值
  3. logicNotDeleteValue 逻辑未删除全局值
  4. 在 POJO 的逻辑删除字段 添加 @TableLogic 注解
  5. 会在 mp 自带查询和更新方法的 sql 后面,追加『逻辑删除字段』=『LogicNotDeleteValue默认值』 删除方法: deleteById()和其他 delete 方法, 底层 SQL 调用的是 update tbl_xxx set 『逻辑删除字段』『logicDeleteValue 默认值』
<!-- 定义MybatisPlus的全局策略配置-->
<bean id ="globalConfiguration" class="com.baomidou.mybatisplus.entity.GlobalConfiguration">
    ...

    <!-- 注入逻辑删除 -->
	<property name="sqlInjector" ref="logicSqlInjector"></property>
    
    <!-- 注入逻辑删除全局值 -->
    <property name="logicDeleteValue" value = "-1"></property>
    <property name="logicNotDeleteValue" value="1"></property>
  
</bean>


<!-- 逻辑删除 -->
<bean id="logicSqlInjector" class="com.baomidou.mybatisplus.mapper.LogicSqlInjector"></bean>

实体类注解方式设置逻辑删除属性:

@TableLogic   // 逻辑删除属性
private Integer logicFlag ;

测试代码:

/**
	 * 测试逻辑删除
	 */
@Test
public void testLogicDelete() {

    Integer result = userMapper.deleteById(1);
    System.out.println("result:" +result );

    User user = userMapper.selectById(1);
    System.out.println(user);
}

九、公共字段自动填充

1.概述

元数据处理器接口 com.baomidou.mybatisplus.mapper.MetaObjectHandler

insertFill(MetaObject metaObject)

updateFill(MetaObject metaObject)

metaobject: 元对象: 是 Mybatis 提供的一个用于更加方便,更加优雅的访问对象的属性,给对象的属性设置值 的一个对象. 还会用于包装对象. 支持对 Object 、Map、Collection等对象进行包装。

本质上 metaObject 获取对象的属性值或者是给对象的属性设置值,最终是要通过 Reflector 获取到属性的对应方法的 Invoker, 最终 invoke。

2.开发步骤

  1. 注解填充字段 @TableFile(fill = FieldFill.INSERT) 查看 FieldFill
  2. 自定义公共字段填充处理器
  3. MP 全局注入 自定义公共字段填充处理器

/**
 * 自定义公共字段填充处理器
 */
public class MyMetaObjectHandler extends MetaObjectHandler {
	
	/**
	 * 插入操作 自动填充
	 */
	@Override
	public void insertFill(MetaObject metaObject) {
		//获取到需要被填充的字段的值
		Object fieldValue = getFieldValByName("name", metaObject);
		if(fieldValue == null) {
			System.out.println("*******插入操作 满足填充条件*********");
			setFieldValByName("name", "weiyunhui", metaObject);
		}
		
	}
	/**
	 * 修改操作 自动填充
	 */
	@Override
	public void updateFill(MetaObject metaObject) {
		Object fieldValue = getFieldValByName("name", metaObject);
		if(fieldValue == null) {
			System.out.println("*******修改操作 满足填充条件*********");
			setFieldValByName("name", "weiyh", metaObject);
		}
	}

}

<!-- 公共字段填充处理器 -->
<bean id="myMetaObjectHandler" class="com.atguigu.mp.metaObjectHandler.MyMetaObjectHandler"> </bean>

<!-- 定义MybatisPlus的全局策略配置-->
<bean id ="globalConfiguration" class="com.baomidou.mybatisplus.entity.GlobalConfiguration">
    ...
    <!-- 注入公共字段填充处理器 -->
    <property name="metaObjectHandler" ref="myMetaObjectHandler"></property>
</bean>

测试代码:

/**
	 * 测试公共字段填充
	 */
@Test
public void testMetaObjectHandler() {
    User user = new User();
    //user.setName("Tom");

    user.setId(5);
    user.setLogicFlag(1);

    userMapper.updateById(user);
}

十、Oracle 主键Sequence

  • MySQL: 支持主键自增。 IdType.Auto

  • Oracle: 序列(Sequence)

    • 实体类配置主键 Sequence @KeySequence(value=”序列名”,clazz=xxx.class 主键属性类型)

    • 全局 MP 主键生成策略为 IdType.INPUT

    • 全局 MP 中配置 Oracle 主键 Sequence:

      com.baomidou.mybatisplus.incrementer.OracleKeyGenerator

    • 可以将@keySequence 定义在父类中,可实现多个子类对应的多个表公用一个 Sequence

1.oracle环境搭建

  • 添加pom依赖

    <!-- Oracle驱动: 因为Oracle授权的问题,不能从Maven的仓库中下载到Oracle驱动 -->
    <dependency>
        <groupId>com.oracle</groupId>
        <artifactId>ojdbc14</artifactId>
        <version>10.2.0.4.0</version>
    </dependency>
    
  • db.properties添加oracle数据库信息

    orcl.driver=oracle.jdbc.OracleDriver
    orcl.url=jdbc:oracle:thin:@localhost:1521:xe
    orcl.username=system
    orcl.password=1234
    
  • applicationContext.xml将数据源设为oracle

    <!-- Oracle -->
    	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    		<property name="driverClass" value="${orcl.driver}"></property>
    		<property name="jdbcUrl" value="${orcl.url}"></property>
    		<property name="user" value="${orcl.username}"></property>
    		<property name="password" value="${orcl.password}"></property>
    	</bean>
    
  • 新建表和序列

    -- 创建一个测试表
    drop table tbl_user;
    create table tbl_user(
    	id number(11) primary key,
        name varchar2(50),
        logic_flag number(11)
    );
    
    -- 序列
    create sequence seq_user start with 100 increment by 2;
    
    -- 序列的常用操作
    -- 查询序列的下一个值
    select seq_user.nextval from dual;
    -- 查询序列的当前值
    select seq_user.currval from dual;
    

2.开发步骤

2.1 实体类配置主键 Sequence @KeySequence(value=”序列名”,clazz=xxx.class 主键属性类型)

2.2 全局 MP 主键生成策略为 IdType.INPUT

2.3 全局 MP 中配置 Oracle 主键 Sequence:

com.baomidou.mybatisplus.incrementer.OracleKeyGenerator

<!-- 配置Oracle主键Sequence -->
<bean id="oracleKeyGenerator" class="com.baomidou.mybatisplus.incrementer.OracleKeyGenerator"></bean>

<!-- 定义MybatisPlus的全局策略配置-->
	<bean id ="globalConfiguration" class="com.baomidou.mybatisplus.entity.GlobalConfiguration">
    ...

    <!-- 注入Oracle主键Sequence -->
    <property name="keyGenerator" ref="oracleKeyGenerator"></property>
</bean>

2.4 测试

/**
	 * 测试Oracle 主键 Sequence
	 */
@Test
public void testOracle() {
    User user = new User();
    user.setLogicFlag(1);
    user.setName("OracleSEQ");
    userMapper.insert(user);
}

将@keySequence 定义在父类中,可实现多个子类对应的多个表公用一个 Sequence

@KeySequence(value="seq_user",clazz=Integer.class)
public abstract class Parent {

}

子类继承:

//@KeySequence(value="seq_user",clazz=Integer.class)
public class User extends Parent {
}

十一、Idea快速开发插件

MybatisX 辅助 idea 快速开发插件,为效率而生.

可以实现 java 与 xml 跳转,根据 Mapper 接口中的方法自动生成 xml 结构.

官方安装: File -> Settings -> Plugins -> Browse Repositories… 输入 mybatisx 安装下载

Jar 安装: File -> Settings -> Plugins -> Install plugin from disk… 选中 mybatisx…jar 安装

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值