一.引用
1.1.作用
替我们生成常用增删改查操作的 SQL 语句。
1.2. 代码官方发布地址
https://gitee.com/free
https://gitee.com/free/Mapper/wikis/1.1-java?parent=1.integration
1.3. 前置知识
MyBatis
Spring
二.快速入门
2.1.创建测试数据
2.1.1. SQL语句
CREATE TABLE `table_emp` (
`emp_id` INT NOT NULL AUTO_INCREMENT ,
`emp_name` VARCHAR(500) NULL ,
`emp_salary` DOUBLE(15,5) NULL ,
`emp_age` INT NULL ,
PRIMARY KEY (`emp_id`)
);
INSERT INTO `table_emp` (`emp_name`, `emp_salary`, `emp_age`) VALUES ('tom', '1254.37', '27');
INSERT INTO `table_emp` (`emp_name`, `emp_salary`, `emp_age`) VALUES ('jerry', '6635.42', '38');
INSERT INTO `table_emp` (`emp_name`, `emp_salary`, `emp_age`) VALUES ('bob', '5560.11', '40');
INSERT INTO `table_emp` (`emp_name`, `emp_salary`, `emp_age`) VALUES ('kate', '2209.11', '22');
INSERT INTO `table_emp` (`emp_name`, `emp_salary`, `emp_age`) VALUES ('justin', '4203.15', '3');
2.1.2.创建Maven工程
2.1.3.Java 实体类
考虑到基本数据类型在 Java 类中都有默认值,会导致 MyBatis 在执行相关操作
时很难判断当前字段是否为 null,所以在 MyBatis 环境下使用 Java 实体类时尽量不
要使用基本数据类型,都使用对应的包装类型。
package com.tedu.java.pojo;
/**
* @author: zyy
* @date: 2022/4/9 10:57
* @description: TODO
* @version: 1.0
* @描述:
**/
public class Employee {
private Integer empId;
private String empName;
private Double empSalary;
private Integer empAge;
public Employee() {
}
public Employee(Integer empId, String empName, Double empSalary, Integer empAge) {
this.empId = empId;
this.empName = empName;
this.empSalary = empSalary;
this.empAge = empAge;
}
public Integer getEmpId() {
return empId;
}
public void setEmpId(Integer empId) {
this.empId = empId;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public Double getEmpSalary() {
return empSalary;
}
public void setEmpSalary(Double empSalary) {
this.empSalary = empSalary;
}
public Integer getEmpAge() {
return empAge;
}
public void setEmpAge(Integer empAge) {
this.empAge = empAge;
}
@Override
public String toString() {
return "Employee{" +
"empId=" + empId +
", empName='" + empName + '\'' +
", empSalary=" + empSalary +
", empAge=" + empAge +
'}';
}
}
2.2. 搭建 MyBatis+Spring 开发环境
2.2.1. 导入所需要的依赖包
<?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>com.tedu.java</groupId>
<artifactId>Mapper01</artifactId>
<version>1.0-SNAPSHOT</version>
<!--引入项目依赖的jar包 -->
<!-- SpringMVC、Spring -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependencies>
<!--引入pageHelper分页插件 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.0.0</version>
</dependency>
<!-- MBG -->
<!-- https://mvnrepository.com/artifact/org.mybatis.generator/mybatis-generator-core -->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.5</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<!-- 返回json字符串的支持 -->
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.8</version>
</dependency>
<!--JSR303数据校验支持;tomcat7及以上的服务器,
tomcat7以下的服务器:el表达式。额外给服务器的lib包中替换新的标准的el
-->
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-validator -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.4.1.Final</version>
</dependency>
<!-- Spring-Jdbc -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<!--Spring-test -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<!-- Spring面向切面编程 -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<!--MyBatis -->
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.2</version>
</dependency>
<!-- MyBatis整合Spring的适配包 -->
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
<!-- 数据库连接池、驱动 -->
<!-- https://mvnrepository.com/artifact/c3p0/c3p0 -->
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
</dependency>
<!-- (jstl,servlet-api,junit) -->
<!-- https://mvnrepository.com/artifact/jstl/jstl -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<!-- junit -->
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/tk.mybatis/mapper -->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper</artifactId>
<version>4.2.1</version>
</dependency>
<!-- log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.7</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<testFailureIgnore>true</testFailureIgnore>
</configuration>
</plugin>
</plugins>
</build>
</project>
2.2.2. 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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
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-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<!--配置数据源-->
<context:property-placeholder location="classpath:dbconfig.properties"></context:property-placeholder>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}"></property>
<property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
<property name="user" value="${jdbc.user}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!--整合Mybatis-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
</bean>
<!-- 原始全类名:org.mybatis.spring.mapper.MapperScannerConfigurer -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.tedu.java.mappers"></property>
</bean>
<!--配置Service自动扫描的包-->
<context:component-scan base-package="com.tedu.java.service"></context:component-scan>
<!--配置声明式事务-->
<bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<aop:config>
<aop:advisor advice-ref="txAdvice" pointcut="execution(* *..*Service.*(..))"></aop:advisor>
</aop:config>
<tx:advice id="txAdvice" transaction-manager="dataSourceTransactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true"/>
<tx:method name="save*" rollback-for="java.lang.Exception" propagation="REQUIRES_NEW"></tx:method>
<tx:method name="remove*" rollback-for="java.lang.Exception" propagation="REQUIRES_NEW"/>
<tx:method name="update*" rollback-for="java.lang.Exception" propagation="REQUIRES_NEW"/>
</tx:attributes>
</tx:advice>
</beans>
2.2.3.数据库配置文件
dbconfig.properties
jdbc.jdbcUrl=jdbc:mysql://localhost:3306/ssm_crud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=UTC
jdbc.driverClass=com.mysql.cj.jdbc.Driver
jdbc.user=root
jdbc.password=123456
2.2.4.log4j配置文件
log4j.rootLogger=DEBUG,myConsole
log4j.appender.myConsole=org.apache.log4j.ConsoleAppender
log4j.appender.myConsole.ImmediateFlush=true
log4j.appender.myConsole.Target=System.out
log4j.appender.myConsole.layout=org.apache.log4j.PatternLayout
log4j.appender.myConsole.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n
log4j.logger.com.mchange.v2=ERROR
2.2.5. mybatis配置文件
mybatis-config.xml
<?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>
2.3.测试
编写测试类:
package com.tedu.java;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
/**
* @author: zyy
* @date: 2022/4/9 11:12
* @description: TODO
* @version: 1.0
* @描述:
**/
public class test {
private ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
/**
* 获取数据库连接
* @throws SQLException
*/
@Test
public void testDataSource() throws SQLException {
DataSource dataSource = context.getBean(DataSource.class);
Connection connection = dataSource.getConnection();
System.out.println(connection);
connection.close();
}
}
2.4.集成 Mapper
2.4.1. 加入 Maven 依赖信息
<!-- https://mvnrepository.com/artifact/tk.mybatis/mapper -->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper</artifactId>
<version>4.2.1</version>
</dependency>
2.4.2. 修改spring配置文件
<!-- 整合通用Mapper所需要做的配置修改: -->
<!-- 原始全类名:org.mybatis.spring.mapper.MapperScannerConfigurer -->
<!-- 通用Mapper使用:tk.mybatis.spring.mapper.MapperScannerConfigurer -->
<bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.tedu.java.mappers"></property>
</bean>
2.4.3. 添加EmployeeMapper接口
package com.tedu.java.mappers;
import com.tedu.java.pojo.Employee;
import tk.mybatis.mapper.common.Mapper;
/**
* 具体操作数据库的Mapper接口,需要继承调用Mapper提供的核心接口Mapper
* Mapper<Employee>
* 泛型为需要操作的实体类
*/
public interface EmployeeMapper extends Mapper<Employee> {
}
三. 常用注解
3.1. @Table 注解
作用:建立实体类和数据库表之间的对应关系。
默认规则:实体类类名首字母小写作为表名。Employee 类→employee 表。
用法:在@Table 注解的 name 属性中指定目标数据库表的表名。
3.2. @Column 注解
作用:建立实体类字段和数据库表字段之间的对应关系。
默认规则:
实体类字段:驼峰式命名
数据库表字段:使用“_”区分各个单词
用法:在@Column 注解的 name 属性中指定目标字段的字段名。
3.3.@Id 注解
通用 Mapper 在执行 xxxByPrimaryKey(key)方法时,有两种情况。
情况 1:没有使用@Id 注解明确指定主键字段
SELECT emp_id,emp_name,emp_salary_apple,emp_age FROM tabple_emp WHERE emp_id = ?
AND emp_name = ? AND emp_salary_apple = ? AND emp_age = ?
之所以会生成上面这样的 WHERE 子句是因为通用 Mapper 将实体类中的所有
字段都拿来放在一起作为联合主键。
情况 2:使用@Id 主键明确标记和数据库表中主键字段对应的实体类字段。
3.4. @GeneratedValue 注解
作用:让通用 Mapper 在执行 insert 操作之后将数据库自动生成的主键值回写到实
体类对象中。
自增主键用法:
序列主键用法:
应用场景:购物车结账
增加商品销量…
减少商品库存…
生成订单数据→封装到 Order 对象中→保存 Order 对象→数据库自动生成主键
值→回写到实体类对象 Order 中
生 成 一 系 列 订 单 详 情 数 据 → List → 在 每 一 个 OrderItem 中 设 置
Order 对象的主键值作为外键→批量保存 List
…
3.5.@Transient 主键
用于标记不与数据库表字段对应的实体类字段。
四. 常用方法
4.1.创建serviceImpl
package com.tedu.java.service;
import com.tedu.java.mappers.EmployeeMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @author: zyy
* @date: 2022/4/9 11:40
* @description: TODO
* @version: 1.0
* @描述:
**/
@Service
public class EmployeeServiceImpl {
@Autowired
private EmployeeMapper employeeMapper;
}
4.2.测试方法
package com.tedu.java;
import com.tedu.java.pojo.Employee;
import com.tedu.java.service.EmployeeServiceImpl;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author: zyy
* @date: 2022/4/9 11:39
* @description: TODO
* @version: 1.0
* @描述:
**/
public class EmployeeMapperTest {
private ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
private EmployeeServiceImpl employeeService = context.getBean(EmployeeServiceImpl.class);
}
4.3.selectOne 方法
/**
* selectOne方法:
* 通用Mapper替我们自动生成的SQL语句。
* 实体类封装查询条件生成where子句规则
* 1.使用非空的值生成where子句
* 2.在条件表达式中使用"="进行比较。
* 3.要求必须返回一个实体类结果,如果有多个则会抛出异常。
*/
@Test
public void testSelectOne(){
//1.创建一个封装查询实体类的对象
Employee employeeQueryCondition = new Employee(null,"bob",5560.11,null);
//2.执行查询
Employee employee = employeeService.getOne(employeeQueryCondition);
System.out.println(employee);
}
public Employee getOne(Employee employeeQueryCondition) {
return employeeMapper.selectOne(employeeQueryCondition);
}
注意:
出现次错误,需要在实体类Employee上添加@Table注解
实体类封装查询条件生成 WHERE 子句的规则:
- 使用非空的值生成 WHERE 子句
- 在条件表达式中使用“=”进行比较
注意:要求必须返回一个实体类结果,如果有多个,则会抛出异常
4.3.xxxByPrimaryKey 方法
需要使用@Id 主键明确标记和数据库表主键字段对应的实体类字段,否则通用
Mapper 会将所有实体类字段作为联合主键。
/**
* @Id
* 通用mapper在执行xxxselectByPrimaryKey(key)方法时,有两种情况
* 情况1:
* 没有使用@Id注解明确指定主键字段
* 通用mapper会将实体类中所有的字段都拿来放在一起作为联合主键。
* 情况2.
* 使用@Id主键明确标记和数据库中主键字段作为主键。
*
*
* 如果没有@Id注解的话,通用mapper会将实体类中所有的字段都拿来放在一起作为联合主键。
*/
@Test
public void testSelectByPrimaryKey(){
//提供id值
Integer empId=3;
//执行按主键进行查询
Employee employee =employeeService.getEmplyooById(empId);
//输出打印结果
System.out.println(employee);
}
public Employee getEmplyooById(Integer empId) {
return employeeMapper.selectByPrimaryKey(empId);
}
4.4.existsWithPrimaryKey方法
/**
* 判断是否存在该主键
*/
@Test
public void testExistsWithPrimaryKey(){
//提供主键
Integer empId=3;
//执行查询
boolean flag = employeeService.isExists(empId);
System.out.println(flag);
}
public boolean isExists(Integer empId) {
return employeeMapper.existsWithPrimaryKey(empId);
}
4.5.Insert方法
@Test
public void testInsert(){
//1.创建一个实体类对象封装要保存到数据库中的数据
Employee employee = new Employee(null, "emp02", 2000.00, 25);
employeeService.saveEmployee(employee);
}
public void saveEmployee(Employee employee) {
employeeMapper.insert(employee);
}
4.6.InsertSelective方法
/**
* InsertSelective非主键字段如果为null,则不加入到SQL中。
*/
@Test
public void testInsertSelective(){
//1.创建一个实体类对象封装要保存到数据库中的数据
Employee employee = new Employee(null, "emp02", 4000.00, null);
employeeService.saveEmployeeSelective(employee);
}
public void saveEmployeeSelective(Employee employee) {
employeeMapper.insertSelective(employee);
}
五. QBC 查询
5.1.概念
Query By Criteria
Criteria 是 Criterion 的复数形式。意思是:规则、标准、准则。在 SQL 语句中相当
于查询条件。
QBC 查询是将查询条件通过 Java 对象进行模块化封装。
5.2.实例代码
@Test
public void testSelectByExample(){
//1.目标:WHERE(EMP_salary>? AND emp_age<?) or (EMP_salary<? AND emp_age>?)
//创建Example对象
Example example = new Example(Employee.class);
//设置排序信息
example.orderBy("empSalary").asc().orderBy("empAge").desc();
//设置去重
example.setDistinct(true);
//设置select字段
example.selectProperties("empName","empSalary");
//通过Example对象创建Criteria对象
Example.Criteria criteria01 = example.createCriteria();
Example.Criteria criteria02 = example.createCriteria();
//在两个Criteria对象中分别设置查询条件
//property参数:实体类的属性名
//value参数:实体类的属性值
criteria01.andGreaterThan("empSalary",3000).andLessThan("empAge",25);
criteria02.andLessThan("empSalary",5000).andGreaterThan("empAge",30);
//使用OR关键字来组装两个Criteria对象
example.or(criteria02);
//执行查询
List<Employee> employees = employeeService.getEmpListByExample(example);
for(Employee employee:employees){
System.out.println(employee);
}
}
六. 逆向工程
6.1原生 MyBatis 逆向工程和通用 Mapper 逆向工程对比
6.2. 参考文档地址
https://github.com/abel533/Mapper/wiki/4.1.mappergenerator
6.3.逆向工程创建(Maven方式)
使用Maven插件的一个好处是可以将Maven中的属性使用${property}形式在generatorConfig.xml中引用。
6.3.1.在 Maven的 pom.xml 中properties声明
<properties>
<!--
${basedir}:引用工程的根目录
targetJavaProject:声明存放源码的目录位置
targetMapperPackage:声明MBG生成xxxMapper接口后存放的package位置
targetModelPackage:声明MBG生成实体类后存放的package位置
targetResourcesProject:声明存放资源文件和XML配置文件的目录位置
targetXMLPackage:声明存放具体XxxMapper.xml 文件的目录位置
-->
<!-- MyBatis Generator -->
<!-- Java接口和实体类 -->
<targetJavaProject>${basedir}/src/main/java</targetJavaProject>
<targetMapperPackage>com.tedu.java.mappers</targetMapperPackage>
<targetModelPackage>com.tedu.java.com.tedu.java.pojo</targetModelPackage>
<!-- XML生成路径 -->
<targetResourcesProject>${basedir}/src/main/resources</targetResourcesProject>
<targetXMLPackage>mappers</targetXMLPackage>
<!-- 依赖版本 -->
<!--
mapper.version:通用mapper版本
-->
<mapper.version>4.0.0-beta3</mapper.version>
<mysql.version>8.0.26</mysql.version>
</properties>
上面是pom.xml中properties配置的部分内容。这里配置了MBG配置文件中常用到的几个路径以及包名。还包含了通用Mapper的版本和数据库JDBC驱动的版本。
6.3.2.在 pom 文件中添加 plugin 配置(MBG的Maven插件配置)
<build>
<plugins>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.2</version>
<!--
配置generatorConfig.xml配置文件的路径
-->
<configuration>
<configurationFile>${basedir}/src/main/resources/generator/generatorConfig.xml</configurationFile>
<overwrite>true</overwrite>
<verbose>true</verbose>
</configuration>
<!--
MBG插件的依赖信息
-->
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper</artifactId>
<version>${mapper.version}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
这里配置了MBG插件,并且配置了generatorConfig.xml配置文件的路径。另外还有两个依赖,分别是JDBC驱动以及通用Mapper(提供了MBG插件)。
6.3.3.所需依赖
<dependencies>
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper</artifactId>
<version>4.0.0-beta3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.2</version>
</dependency>
<!-- MyBatis整合Spring的适配包 -->
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
</dependencies>
6.3.4. 逆向工程 generatorConfiguration.xml 配置
在项目resource目录下创建generator包,存放generatorConfiguration.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!--
引入外部属性文件
-->
<properties resource="config.properties"/>
<context id="Mysql" targetRuntime="MyBatis3Simple" defaultModelType="flat">
<property name="beginningDelimiter" value="`"/>
<property name="endingDelimiter" value="`"/>
<!--
配置通用Mapper的MBG插件相关信息
-->
<plugin type="${mapper.plugin}">
<property name="mappers" value="${mapper.Mapper}"/>
</plugin>
<jdbcConnection driverClass="${jdbc.driverClass}"
connectionURL="${jdbc.url}"
userId="${jdbc.user}"
password="${jdbc.password}">
</jdbcConnection>
<!--
配置Java实体类存放位置
-->
<javaModelGenerator targetPackage="${targetModelPackage}"
targetProject="${targetJavaProject}"/>
<!--
配置XML映射文件XxxMapper.xml的存放位置
-->
<sqlMapGenerator targetPackage="${targetXMLPackage}" targetProject="${targetResourcesProject}"/>
<!--
配置mapper接口XxxMapper.java存放位置
-->
<javaClientGenerator targetPackage="${targetMapperPackage}"
targetProject="${targetJavaProject}"
type="XMLMAPPER"/>
<!--
根据数据库表生成Java文件的相关规则
tableName="%" 表示数据库中所有的表都参与逆向工程,此时使用默认规则
默认规则:table_depte 类名:TableDept
不符合默认规则时需要使用tableName和 domainObjectName两个属性明确指定
generatedKey:配置主键生成策略
-->
<table tableName="table_emp" domainObjectName="Employee">
<generatedKey column="emp_id" sqlStatement="Mysql" identity="true"/>
</table>
</context>
</generatorConfiguration>
可以看到这个配置文件中的大多数属性都使用${}形式替代了。使用引入了config.properties属性配置,该文件内容如下:
# 数据库配置
jdbc.driverClass=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/ssm_crud?serverTimezone=Asia/Shanghai
jdbc.user=root
jdbc.password=123456
#c3p0
jdbc.maxPoolSize=50
jdbc.minPoolSize=10
jdbc.maxStatements=100
jdbc.testConnection=true
# 通用Mapper配置
mapper.plugin=tk.mybatis.mapper.generator.MapperPlugin
mapper.Mapper=tk.mybatis.mapper.common.Mapper
使用配置文件的目的是因为系统多处地方使用了这种配置,因而使用一个属性文件可以方便的保持一致。
除了引用配置文件中的属性外,部分还使用了pom.xml中的属性。这种方式使用起来更灵活。
6.3.5. 运行通用Mapper
在pom.xml这一级目录的命令行窗口执行mvn mybatis-generator:generate即可(前提是配置了mvn)。
6.4.生成的资源
EmployeeMapper 接口:
接口自动继承配置的通用Mapper接口,自动包含泛型实体。
6.5.逆向工程测试
添加myatis配置文件和log4.xmlj以及数据库配置文件
mybatis-config.xml
<?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>
<properties resource="dbconfig.properties"></properties>
<!--2.settings包含很多重要的设置项
setting:用来设置每一个设置项
name:设置项名
value:设置项取值-->
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<!--3.typeAliases,可以为我们的java类型起别名
typeAlias:为摸个java类起别名
type:指定要起别名的类型全类型;默认类型就是类的小写 employee
alias:指定新的别名
别名不区分大小写
-->
<typeAliases>
<!--<typeAlias type="com.tedu.com.tedu.com.tedu.java.pojo.Employee"></typeAlias>-->
<!--批量起别名
package:为某个包下的所有类批量起别名
name:指定包名(为当前包以及下面所有的后带包的每一个类都起一个默认的别名)
使用@Alias注解为某个类型指定新的别名
-->
<package name="com.tedu.com.tedu.com.tedu.java.pojo"/>
</typeAliases>
<!--4.environments:环境设置,mybatis可以配置多种环境 default指定某个环节
environment:配置一个具体的环境信息,必须有两个标签,id代表环境的唯一标识
transactionManager:事务管理器
type:事务管理器的类型 JDBC|MANAGED
自定义事务管理器:实现TransactionFactory接口
dataSource:数据源;UNPOOLED|POOLED|JNDI
自定义数据源实现DataSourceFactory接口
-->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driverClass}"/>
<property name="url" value="${jdbc.jdbcUrl}"/>
<property name="username" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!--databaseIdProvider:支持多数据厂商的;
type=DB_VENDOR VendorDatabaseIdProvider
作用就是得到数据库厂商的标识,mybatis就能根据数据库厂商标识(驱动getDatabaseProductName())来执行不同的sql;
-->
<databaseIdProvider type="DB_VENDOR">
<!--为不同的数据库厂商起别名-->
<property name="Mysql" value="mysql"/>
</databaseIdProvider>
<!-- 将我们写好的sql映射文件(EmployeeMapper.xml)一定要注册到全局配置文件(mybatis-config.xml)中 -->
<!--mappers:将sql映射注册到全局配置中-->
<mappers>
<package name="com.tedu.java.mappers"/>
</mappers>
</configuration>
log4j.properties:
log4j.rootLogger=DEBUG,myConsole
log4j.appender.myConsole=org.apache.log4j.ConsoleAppender
log4j.appender.myConsole.ImmediateFlush=true
log4j.appender.myConsole.Target=System.out
log4j.appender.myConsole.layout=org.apache.log4j.PatternLayout
log4j.appender.myConsole.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n
log4j.logger.com.mchange.v2=ERROR
dbconfig.properties:
jdbc.jdbcUrl=jdbc:mysql://localhost:3306/ssm_crud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=UTC
jdbc.driverClass=com.mysql.cj.jdbc.Driver
jdbc.user=root
jdbc.password=123456
测试类
package com.tedu.java;
import com.tedu.java.com.tedu.java.pojo.Employee;
import com.tedu.java.mappers.EmployeeMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
import tk.mybatis.mapper.mapperhelper.MapperHelper;
import java.io.InputStream;
import java.util.List;
/**
* @author: zyy
* @date: 2022/4/9 12:55
* @description: TODO
* @version: 1.0
* @描述:
**/
public class Mappertest {
@Test
public void test() throws Exception {
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sessionFactory.openSession();
//**********************
//按照Java方式整合通用Mapper的特殊设置
//1.创建MapperHelper 对象
MapperHelper mapperHelper = new MapperHelper();
//2.通过MapperHelper 对象对MyBatis原生的Configuration对象进行处理
mapperHelper.processConfiguration(sqlSession.getConfiguration());
//**********************
EmployeeMapper mapper = sqlSession.getMapper(EmployeeMapper.class);
List<Employee> employees = mapper.selectAll();
employees.forEach(System.out::println);
sqlSession.close();
}
}
运行结果:
七.自定义 Mapper接口
7.1.让我们可以根据开发的实际需要对 Mapper接口进行定制。
7.2.创建自定义 Mapper接口
public interface MyMapper<T>extends SelectAllMapper<T>, SelectByExampleMapper<T>,MyBatchUpdateMapper<T> {
}
public interface EmployeeMapper extends MyMapper<Employee> {
}
7.3.配置 MapperScannerConfigurer 注册 MyMapper
<bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.tedu.java.mappers"></property>
<property name="properties">
<value>
mappers = com.tedu.java.minMappers.MyMapper
</value>
</property>
</bean>
八.通用 Mapper 接口扩展
8.1.说明
这里的扩展是指增加通用 Mapper 没有提供的功能。
8.2.举例
我们来仿照写一个批量 update。假设我们想生成下面这样的 SQL 语句:
UPDATE tabple_emp SET emp_name=?,emp_age=?,emp_salary=? where emp_id=? ;
UPDATE tabple_emp SET emp_name=?,emp_age=?,emp_salary=? where emp_id=? ;
UPDATE tabple_emp SET emp_name=?,emp_age=?,emp_salary=? where emp_id=?
为了生成上面那样的 SQL 语句,我们需要使用到 MyBatis 的 foreach 标签。
<foreach collection="list" item="record" separator=";" >
UPDATE tabple_emp
SET emp_name=#{record.empName},
emp_age=#{record.empAge},
emp_salary=#{record.empSalary}
where emp_id=#{record.empId}
</foreach>
8.3.我们需要提供的接口和实现类
1. 注册接口
MyMapper接口
public interface MyMapper<T>extends SelectAllMapper<T>, SelectByExampleMapper<T>,MyBatchUpdateMapper<T> {
}
继承的MyBatchUpdateMapper接口
public interface MyBatchUpdateMapper<T> {
@UpdateProvider(type = MyBatchUpdateProvider.class,method = "dynamicSQL")
void batchUpdate(List<T>list);
}
具体的实现类:MyBatchUpdateProvider
package com.tedu.java.minMappers;
import org.apache.ibatis.mapping.MappedStatement;
import tk.mybatis.mapper.entity.EntityColumn;
import tk.mybatis.mapper.mapperhelper.EntityHelper;
import tk.mybatis.mapper.mapperhelper.MapperHelper;
import tk.mybatis.mapper.mapperhelper.MapperTemplate;
import tk.mybatis.mapper.mapperhelper.SqlHelper;
import java.util.Set;
/**
* @author: zyy
* @date: 2022/4/5 13:53
* @description: TODO
* @version: 1.0
* @描述:
**/
public class MyBatchUpdateProvider extends MapperTemplate {
public MyBatchUpdateProvider(Class<?> mapperClass, MapperHelper mapperHelper) {
super(mapperClass, mapperHelper);
}
public String batchUpdate(MappedStatement mappedStatement) {
//创建一个StringBuilder对象用于拼接SQL语句
StringBuilder builder = new StringBuilder();
//拼接foreach
builder.append("<foreach collection=\"list\" item=\"record\" separator=\";\">");
//获取实体类对应的class对象
Class<?> entityClass = super.getEntityClass(mappedStatement);
//获取表名
String tableName = super.tableName(entityClass);
String updateClause = SqlHelper.updateTable(entityClass,tableName);
builder.append(updateClause);
builder.append("<set>");
//获取所有的字段信息
Set<EntityColumn> columns = EntityHelper.getColumns(entityClass);
String idColumn = null;
String idHolder = null;
for(EntityColumn entityColumn:columns){
//判断当前列是否是主键
if(entityColumn.isId()){
//缓存主键的字段名和字段值
idColumn = entityColumn.getColumn();
idHolder = entityColumn.getColumnHolder("record");
}else{
//使用非主键字段拼接set语句
String column = entityColumn.getColumn();
String record = entityColumn.getColumnHolder("record");
builder.append(column).append("=").append(record).append(",");
}
}
builder.append("</set>");
//使用前面缓存的主键值和主键名拼接where字句
builder.append("WHERE ").append(idColumn).append("=").append(idHolder);
builder.append("</foreach>");
return builder.toString();
}
}
九.二级缓存
9.1.myBatis 配置文件开启二级缓存功能
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
9.2.在 XxxMapper 接口上使用@CacheNamespace 注解
@CacheNamespace
public interface EmployeeMapper extends MyMapper<Employee> {
}