Mybatis3-入门

[toc]

0、资料

视频:

书:

  • SSM从零开始学

博客:


1、Mybatis 概述

Mybaits3 也就是 ibatis3。Mybatis是一个持久层的框架。

为什么使用 Mybatis ?

  • Mybatis 是半自动的持久层框架
  • JDBC硬编码,耦合度高
  • Hibernate 和 JPA,全自动框架,对复杂的SQL语句也不好处理

Mybatis 官网地址:MyBatis 3 -官方文档-中文

Mybatis 下载地址:https://github.com/mybatis/mybatis-3/releases

原生的接口式编程:Dao =》 DaoImpl

Mybatis口式编程: Dao =》 dao接口的XML映射配置文件

注意:

  • 配置文件的提示:XML中引入DTD约束
  • SqlSession使用完后必须手动关闭
  • SqlSession 和 Connection 一样,都是 非线程安全的,每次使用都应该重新获取对象
  • Mybatis不用写Dao的实现类,Mybatis会根据XML映射配置文件生成代理对象
  • SqlSession.getMapper(UserDao.class) 得到的是代理对象

1.1、 初次使用Mybatis-案例

 实体类-User:

1
2
3
4
5
6
7
8
9
package com.beans;
// 以下省略构造函数getter/setter、toString的代码
public class User {
// 属性名应该尽量与数据库中的一致,如过不一致,则需要在SQL中手动取别名取成一致
private int uid;
private String username;
private String pwd;
private int money;
}

Dao接口-UserDao:

1
2
3
4
5
6
7
8
9
10
11
package com.dao;

import org.apache.ibatis.annotations.Select;

import com.beans.User;

public interface UserDao {
// @Select("select * from user where uid = #{uid}")
public User getUser(int uid);
}

全局配置文件:app.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?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>
// 配置数据库的信息
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/springstudy"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>

// 注册Dao接口的映射配置文件
<mappers>
<mapper resource="com/conf/UserMapper.xml"/>
</mappers>
</configuration>

Dao接口的映射配置文件【注解版】:UserMapper

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

// namespace: 表示Dao接口的全类名
// mapper 标签内,如果使用注解来执行SQL,则不用写SQL语句的标签;否则,写
<mapper namespace="com.dao.UserDao">

</mapper>

Dao接口的映射配置文件【XML版】:UserMapper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

// namespace: 表示Dao接口的全类名
// mapper 标签内,如果使用注解来执行SQL,则不用写SQL语句的标签;否则,写
// select标签中,
// - id :方法名,
// - resultType :返回值类型
// - #{} :形参,SQL语句的占位符
<mapper namespace="com.dao.UserDao">
<select id="getUser" resultType="com.beans.User">
select * from user where uid = #{uid}
</select>
</mapper>

测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import java.io.*;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.*;
import com.beans.User;
import com.dao.UserDao;

public class Test {
public static void main(String[] args) {
try {
InputStream in = Resources.getResourceAsStream("app.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
SqlSession session = sqlSessionFactory.openSession();
UserDao dao = session.getMapper(UserDao.class);
User user = dao.getUser(1);

// User [uid=1, username=张三, pwd=123, money=1000]
System.out.println(user);

} catch (IOException e) {
e.printStackTrace();
}finally{
// 关闭session
session.close();
}
}
}

1.2、Maven-POM配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<?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.cyw</groupId>
<artifactId>SSM-01</artifactId>
<version>1.0-SNAPSHOT</version>

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.26</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.9</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.14</version>
</dependency>
</dependencies>


<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<testFailureIgnore>true</testFailureIgnore>
</configuration>
</plugin>
</plugins>
</build>

</project>

1.3、Mybatis 的几个对象

  • SqlSessionFactoryBuilder对象:创建完SqlSessionFactory对象后就没用了。
  • SqlSessionFactory对象:一般设为单例模式
  • SqlSession对象:线程不安全,每次用完要手动关闭。

2、Mybatis 全局配置文件

Mybatis 全局XML配置文件是为了注册信息【也可以通过new配置对象的方法】,包括:

  • 环境信息【数据库、事务管理器】
  • dao接口的映射配置文件的信息

Mybatis 全局XML配置文件中的标签顺序是有规定的,具体顺序见官网。

mybatis-config.xml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?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>

// default属性:指定当前使用哪种环境
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/springstudy"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>

// 指定Dao接口的映射配置文件的路径【必选】
<mappers>
<mapper resource="com/conf/UserMapper.xml"/>

// 或者直接在DAO接口上使用注解写SQL,然后再全局配置中注册接口
// <mapper class="com.dao.UserDao"/>
</mappers>

</configuration>

2.1、 properties标签

Mybatis可以使用properties标签来引入外部的properties文件中的配置【一般是数据库配置信息】。

一般配置文件由Spring来导入,所以Mybatis的数据库配置不常用。

properties标签的两个属性:

  • resource:引入类路径下的配置
  • url:引入网络路径下的配置

例如:

外部properties配置文件-db.properties:

1
2
3
4
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/springstudy
jdbc.username=root
jdbc.password=root

全局配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?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="com/conf/db.properties"></properties>
<!-- <properties url="域名"></properties> -->

// 配置信息
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.Driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>


<mappers>
<!-- <mapper resource="com/conf/UserMapper.xml"/> -->
<mapper class="com.dao.UserDao"/>
</mappers>
</configuration>

2.2、数据表的属性名由下划线转驼峰

在Mybatis的全局配置文件中,使用mapUnderscoreToCamelCase,该配置是在 settings 标签setting子标签中设置的。【 settings 标签 中只能放 setting 标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?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>

// 全局设置
<settings>
// 开启:自动将数据库的属性名由 下划线 转 驼峰
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

// 配置信息
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.Driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>

// dao接口的映射配置文件
<mappers>
<!-- <mapper resource="com/conf/UserMapper.xml"/> -->
<mapper class="com.dao.UserDao"/>
</mappers>

</configuration>

2.3、配置全类名的别名

注意:

  • 别名不区分大小写
  • Mybatis内置了一部分别名【基本数据类型、包装类、集合类型、日期类型】

typeAliases标签可以用来设置多个类的别名。

给单个类取别名(1):

<typeAlias alias="别名" type="全类名"/>是一个别名处理器,可以给全类名设置别名,方便程序员写全类名.

typeAliases标签alias属性默认就是类名的小写

给单个类取别名(2):

在dao接口上(或者某个需要设置别名的类上)使用注解(@Alias("别名"))。

此方式可以在批量取别名的方式出现别名冲突时使用。

给一个包中的全部类取别名(批量取别名):

<package name="包名"/>可以给当前包以及子包的全部类取一个默认别名(默认别名格式:类名小写)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<?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>

// 给全类名取别名
<typeAliases>
<!--
<typeAlias alias="user" type="com.entity.User"/>
等价于
<typeAlias type="com.entity.User"/>
-->
<typeAlias type="com.entity.User"/>
<typeAlias alias="Book" type="com.entity.Book"/>

<!-- 批量取别名 -->
<package name="包名" />
</typeAliases>

// 全局设置
<settings>
// 开启:自动将数据库的属性名由 下划线 转 驼峰
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

// 配置信息
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.Driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>

// dao接口的映射配置文件
<mappers>
<!-- <mapper resource="com/conf/UserMapper.xml"/> -->
<mapper class="com.dao.UserDao"/>
</mappers>

</configuration>

2.4、类型处理器

typeHandlers的作用:建立Java类型数据库类型的桥梁。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<?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>

<typeHandlers>
<package name="com.cyw.Example"/>
</typeHandlers>


// 给全类名取别名
<typeAliases>
<typeAlias type="com.entity.User"/>
<typeAlias alias="Book" type="com.entity.Book"/>
<!-- 批量取别名 -->
<package name="包名" />
</typeAliases>

// 全局设置
<settings>
// 开启:自动将数据库的属性名由 下划线 转 驼峰
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

// 配置信息
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${jdbc.Driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>

// dao接口的映射配置文件
<mappers>
<!-- <mapper resource="com/conf/UserMapper.xml"/> -->
<mapper class="com.dao.UserDao"/>
</mappers>

</configuration>

2.4、插件简介

插件可以拦截以下Mybatis的四大对象的一些方法。

四个对象:

  • StatementHandler
  • ParamterHandler
  • ResultSetlHandler
  • Executor

2.5、多个环境的配置

environments标签,可以包括多个environment标签,并利用id属性指定一个默认使用的环境,每个环境必须要配置事务管理器数据源

一般使用Spring来做事务控制,所以Mybatis的事务管理器仅做了解

transactionManager的type属性的取值:【jdbc | managed | 自定义的事务管理器】

dataSource的type属性的取值:【pooled | unpooled | jndi | 自定义的数据源】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?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>

// 多个环境
<environments default="development">

<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/springstudy"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>

<environment id="test">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/springstudy"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>

<mappers>
<!-- <mapper resource="com/conf/UserMapper.xml"/> -->
<mapper class="com.dao.UserDao"/>
</mappers>
</configuration>

2.6、支持不同厂商的数据库

databaseIdProvider标签,可以让 Mybatis 支持不同厂商的数据库。

步骤:

  • 全局配置文件中,配置databaseIdProvider标签
  • 在dao接口的映射配置文件中,SQL语句标签的databaseId属性设为全局配置文件中厂商property标签的value属性的值

全局配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<?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>

// 数据库厂商
<databaseIdProvider type="DB_VENDER">
<property name="MySQL" value="mysql" />
<property name="Oracle" value="oracle" />
<property name="SQL Server" value="sqlserver" />
</databaseIdProvider>

// 环境
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/springstudy"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>

<mappers>
<!-- <mapper resource="com/conf/UserMapper.xml"/> -->
<mapper class="com.dao.UserDao"/>
</mappers>
</configuration>

映射配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.dao.UserDao">
<select id="getUser1" resultType="com.beans.User"
databaseId="mysql">
select * from user where uid = #{uid}
</select>

<select id="getUser1" resultType="com.beans.User"
databaseId="sqlserver">
select * from user_tb where uid = #{uid}
</select>
</mapper>

3、Mybatis 映射配置文件

Mybatis 映射配置文件【必须要有,除非使用注解方式且已在mapper标签中注册接口】

映射配置文件中,方法的返回值:

Mybatis的增删改方法要想由返回值可直接在方法的返回值,无需像查询一样单独定义返回值属性。

映射配置文件中,方法传参:

方法传参可以直接使用全类名,SQL语句中的参数占位符可以使用#{JavaBean中的属性名}

1
2
3
<select id="getUserByUid" resultType="com.entity.User" >
select * from user where uid = #{uid}
</select>

映射配置文件中,主键自增:

MySQL支持自增主键,Mybatis利用了原生JDBC中的Statement对象的statement.getGeneratedKeys()方法,

制作了一个属性useGeneratedKeys,默认值为false(关闭主键自增策略),配合keyProperty属性使用(指定Mybatis获取自增主键后,赋值给JavaBean的哪个属性)

UserMapper.xml:

1
2
3
4
<insert id="addUser" parameterType="com.entity.User"  
useGeneratedKeys="true" keyProperty="uid">
insert into user values(#{uid},#{username},#{pwd},#{money});
</insert>

Oracle不支持自增主键,则使用序列来模拟自增,每次插入的数据的主键是从序列中拿到的值,insert标签内配合selectKey标签。

3.1、增删改查-案例

bean:

1
2
3
4
5
6
7
package com.entity;
public class User {
private int uid;
private String username;
private String pwd;
private int money;
}

mybatis-conf.xml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?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>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/springstudy"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>

<mappers>
<mapper resource="com/conf/UserMapper.xml"/>
</mappers>
</configuration>

UserMapper.xml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.dao.UserDao">
// 查询
<select id="getUserByUid" resultType="com.entity.User" >
select * from user where uid = #{uid}
</select>
// 插入
<insert id="addUser" parameterType="com.entity.User">
insert into user values(#{uid},#{username},#{pwd},#{money});
</insert>
// 更新
<update id="updateUser" parameterType="com.entity.User">
update user
set username=#{username},pwd=#{pwd},money=#{money}
where uid=#{uid}
</update>
// 删除
<delete id="delUser">
delete from user where uid=#{uid}
</delete>
</mapper>

3.2、方法参数的处理

单个参数:

#{},不会做任何处理,直接传值(参数名随便写都一样)

例如:public User getUser(int uid)

多个参数:【待定,测试时无法使用】

会做处理,多个参数会被封装为一个Map集合,#{}就是取Map中指定的Key的值。

在封装参数Map时,key就是 param1 paramn(或参数的索引号),value才是用户真正传入的参数值。

public User getUser(int uid,String username)

命名参数:

需要明确封装参数Map的Key,即:在接口的方法的参数前使用注解@Param("参数Map的键名")

1
2
3
4
5
6
7
8
9
package com.dao;
import org.apache.ibatis.annotations.Param;
import com.entity.User;

public interface UserDao {
public User getUserByUid(int uid);
public User getUser(@Param("uid") int uid,@Param("username") String username);
}

参数为Collcetion集合或数组的处理:

参数为Collcetion集合或数组时,即使只有一个参数,也会将参数封装为Map。

参数Map的Key键为:

  • Collection:collection
  • List:list
  • 数组:array
1
2
3
#{list[0]}
#{collection[0]}
#{array[0]}

小结1(应用场景):

但参数时,参数命名无所谓。

如果传入的参数很多,且是业务数据模型,可以用传入JavaBean对象的方式来代替。

如果传入的参数很多,但不是业务数据模型,不经常使用,可以用传入Map集合的方式来代替。

如果传入的参数很多,但不是业务数据模型,经常使用,可以用传入TO数据传输对象的方式来代替(如:分页对象)。

小结2(应用方式):

当参数过多时,为了不混乱,可以在dao接口的参数前加上@Param("map参数名")来封装使用的参数map的key,使用#{key名}就可以取出参数map中指定的key所对应的value。

${}#{}来取值的区别:

  • #{}:采用预编译的形式,将参数设置到SQL语句中,类似JDBC中的 preparedStatement
  • ${}:直接取值,类似JDBC中的Statement

大多数情况下应该使用#{},但在原生JDBC不支持占位符的地方可以使用${}(如:sql语句中的表名、排序的字段名、排序顺序)

#{}取值方式的丰富的规则:

规定了参数的一些规则:

  • javaType、jdbcType、mode(存储过程)、numericScale、resultMap、typeHandler、jdbcTypeName、expression
  • javaType通常在数据为null的情况下被设置【有些数据库,如Oracle无法识别mybatis对null值的默认处理】
1
2
// 在映射配置文件中的SQL语句处
#{email,jdbcType=NULL}

3.3、resultMap 标签(关系映射)

resultMap标签的作用:定义结果集的封装规则。

步骤:

1、先在映射配置文件中利用 resultMap 标签自定义JavaBean的封装规则,resultMap 标签的type属性用来绑定某个已知的JavaBean的全类名,id属性作为唯一标识。

2、resultMap 标签指定主键(标签内)<id column="数据表的列名" property="javabean的属性名"/><result column="数据表的列名" property="javabean的属性名"/> 指定数据表的普通属性的封装,如果没有手动指定result 子标签,则自动封装。

3、association、collection两个子标签用于指定关联属性(类型为类的属性),property的值为JavaBean的属性名,javaType的值为类型的全类名(association 子标签),select属性的值为另一个Dao接口中的方法的全类名,column属性的值为数据表中将值传给方法的列,ofType属性的值为集合中元素的类型的全类名(collection 子标签)。

discriminator子标签:鉴别器,属性column的值为数据表的列,属性javaType的值为列所对应的 java类型

关系映射:

  • 一对一(association 子标签):【类A有一个类B的属性】类A的映射配置文件中,association子标签的select属性绑定类B的Dao接口的查询方法,该查询方法的返回值为一个对象。(两个类的关联属性是一个2类型)
  • 一对多(collection 子标签):【类A有一个类B的属性,且是集合类型】类A的映射配置文件中,association子标签的select属性绑定类B的Dao接口的查询方法,该查询方法的返回值为一个集合。(两个类的关联属性是一个集合类型)
  • 多对多(两个实体类都使用collection 子标签):【类A有一个类B的属性,且是集合类型,类B有一个类A的属性,且是集合类型】类A的映射配置文件中,association子标签的select属性绑定类B的Dao接口的查询方法,该查询方法的返回值为一个集合。类B的映射配置文件中,association子标签的select属性绑定类A的Dao接口的查询方法,该查询方法的返回值为一个集合。(两个类各自有一个关联属性,且各自是一个集合类型)

关系映射在编写 association 标签的时候主要有 嵌套结果嵌套查询 两种:

  • 嵌套结果【多表关联的语句在SQL里写】:property + javaType
  • 嵌套查询【多表关联的语句在各自的接口里写】:property + javaType + column + select

小结:

通用:

  • column : 数据表的列名
  • property:javabean的属性名
  • javaType: javabean的全类名(javaBean属性的类型)
  • fetch-Type: 懒加载【lazy(默认) | eager】

【嵌套查询】:

  • id子标签:用于定义主键的映射关系
  • result子标签:用于定义其他属性的映射关系
  • discriminator子标签:使用结果值来决定使用哪个resultMap

【嵌套结果】:

  • select: “查询”方法的全类名
  • column: 数据表的列名
  • property : select 属性的查询结果传给property属性绑定的 javaBean属性

【一对一】:association标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 【嵌套结果的方式】
// com.cyw.dao.StuMapper接口

<resultMap id="StuRst" type="com.cyw.po.Stu">
<id property="sid" column="id"/>
<result property="name" column="name"/>
<result property="sex" column="sex"/>
<association property="card" column="cardId" javaType="com.cyw.po.StuCard">
<id property="id" column="id"/>
<result property="code" column="code"/>
</association>
</resultMap>

<select id="getStuBySid" resultMap="StuRst">
select stu.* ,stuIdCard.code
from stu,stuIdCard
where stu.id = #{sid}
and stu.id = stuIdCard.id;
</select>

【一对多】:collection标签(在的那方的映射配置文件中使用)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 【嵌套结果的方式】
// com.cyw.dao.ClassesMapper

<resultMap id="classesRst" type="com.cyw.po.Classes">
<id property="cid" column="cid"/>
<result property="cname" column="cname"/>
<collection property="stuList" javaType="list" ofType="com.cyw.po.Stu">
<id property="sid" column="id"/>
<result property="name" column="name"/>
<result property="sex" column="sex"/>
<association property="card" column="cardId" javaType="com.cyw.po.StuCard">
<id property="id" column="id"/>
<result property="code" column="code"/>
</association>
</collection>
</resultMap>

<select id="getClassesByCid" resultMap="classesRst">
select classes.*,stu.*,stuIdCard.`code`
from classes,stu,stuIdCard
where classes.id = #{cid}
and stu.cid = classes.id
and stu.cardId = stuIdCard.id;
</select>


【多对多】:collection标签(在双方的映射配置文件中都要使用,用法类似一对多)

一对一_示例::

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.dao.UserDao">

// 自定义JavaBean类型【嵌套查询】
<resultMap id="myUser" javaType="com.entity.User">
// column : 数据表的列名
// property:javabean的属性名
// javaType: javabean的全类名(javaBean属性的类型)
// fetch-Type: 懒加载【lazy(默认) | eager】
<id column="uid" property="uid" />
<result column="username" property="username" />
<result column="pwd" property="pwd" />
<result column="money" property="money" />
<association property="dept" javaType="com.entity.Dept">
<id column="deptId" property="deptId" />
<result column="deptName" property="deptName" />
</association>
<discriminator javaType="string" column="sex">
<case value="0" resultType="myUser">
// ...
</case>
<case value="1" resultType="myUser">
// ...
</case>
</discriminator>
</resultMap>

// 自定义JavaBean类型【嵌套结果】
<resultMap id="myUser" javaType="com.entity.User">
<id column="uid" property="uid" />
<result column="username" property="username" />
<result column="pwd" property="pwd" />
<result column="money" property="money" />
// select: “查询”方法的全类名
// column: 数据表的列名
// property: select属性的查询结果交给property指定的javaBean属性
<association property="dept"
select="com.entity.DeptDao.getDeptByDeptId"
column="dept"
>
</association>
</resultMap>

<select id="getUserByUid1" resultMap="myUser">
select * from user where uid = #{uid}
</select>

</mapper>

一对多_示例::

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<resultMap type="com.entity.User" id="myUser">
// column : 数据表的列名
// property:javabean的属性名
// javaType: javabean的全类名(javaBean属性的类型)
// fetch-Type: 懒加载【lazy(默认) | eager】
<id column="uid" property="uid" />
<result column="username" property="username" />
<result column="pwd" property="pwd" />
<result column="money" property="money" />
<collection property="deptList" ofType="com.entity.Dept">
<id column="deptId" property="deptId" />
<result column="deptName" property="deptName" />
</collection>
</resultMap>

3.4、select标签

1、返回值类型(resultType属性)

一般情况下:

使用 别名 或 全类名。

返回 List 时:

如果方法的返回值为List集合,则 select标签的 resultType类型应该写List集合中元素的类型

1
2
3
4
5
6
7
8
9
10
11
// dao接口中的方法:	
public List getUserLikeName(@Param("username") String username);

// UserMapper.xml
<select id="getUserLikeName" resultType="com.entity.User">
select * from user where username like #{username}
</select>

// 测试
List<User></User> users = dao.getUserLikeName("%李%");
System.out.println(users);

返回Map 时:

如果方法的返回值为Map集合,则 select标签的 resultType类型应该写map

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// dao接口中的方法:【一条记录封装为map】	
public Map getUserByUid(@Param("uid") int uid);

// UserMapper.xml
<select id="getUserByUid" resultType="map">
select * from user where uid = #{uid}
</select>

// 测试
Map user = dao.getUserByUid(1);
System.out.println(user);

===================================================

// dao接口中的方法:【多条记录封装为map】
// 告诉Mybatis使用哪个属性作为主键
@MapKey("uid")
public Map<Integer,User> getUserLike(@Param("username") String username);

// UserMapper.xml
<select id="getUserLike" resultType="map">
select * from user where username like #{uid}
</select>

// 测试
Map user = dao.getUserLike("%李%");
System.out.println(users);

2、返回值类型(resultMap属性)

引用 resultMap 标签所定义的结果集映射规则,具体见上面的3.3小节的 ResultMap 标签。


3.5、insert、update、delete标签

用法与select标签类型,见上面的select标签的笔记和官方文档的示例:

insert、update标签中,主键相关的属性:

  • 属性useGeneratedKeys="true | false"
  • 属性keyProperty="主键的属性名"
  • 属性keyColumn="主键是第几列"

3.6、SQL标签

sql 标签可以定义一些SQL语句中可以复用的一部分内容,然后在select、insert、update、delte标签中利用<include refid=""></include>标签和property标签来引用该SQL标签。

映射配置文件中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

// ${alias}是占位符,在select语句中,通过property标签传入具体的值
<sql id="userColumns"> ${alias}.id,${alias}.username,${alias}.password </sql>

// 查询
<select id="selectUsers" resultType="map">
select
<include refid="userColumns">
<property name="alias" value="t1"/>
</include>
<include refid="userColumns">
<property name="alias" value="t2"/>
</include>
from some_table t1
cross join some_table t2
</select>

3.7、懒加载

懒加载就是在类A中,有一个类B的属性,当Mybatis查询类A时,不会自动查询类B,只有手动调用查询类B的方法时,才查询类B【即:延迟加载】。

Mybatis默认关闭了懒加载

如何启用懒加载:

在mybatis的全局配置文件中的settings标签中,编写配置。

1
2
3
<settings>
<setting name="lazyLoadingEnabled" value="flase"/>
</settings>
加载方式 lazyLoadingEnabled aggressiveLazyLoading
直接加载 必须是false,默认是false 不管是什么,只要lazyLoadingEnabled是false就是直接加载
侵入式延迟加载 必须是true 必须是true
深度延迟 必须是true 必须是false,默认是false

4、Mybatis 动态SQL

动态SQL:解决传统SQL语句的拼接繁琐的问题。

传统的SQL拼接时,where子句后面有多个多个条件那么就需要在一开始写where 1=1,然后开始拼接。使用动态SQL标签后,则可以不用写where 1=1

动态SQL的标签:

以下标签的使用方式类似JSP中的JSTL标签库的用法:

  • if
  • choose (when, otherwise)
  • trim (where【SQL中的where子句】, set【update操作时的set子句】)
  • foreach

4.1、if 标签:

语法: <if test="拼接的条件"> 拼接的SQL语句 </if>

  • test 属性 中可以使用andor 等逻辑关键字组合多个条件
  • test 属性 中的字符串的判断:abc !=null and abc != ''
  • test 属性 中的数字的判断【需要使用转义字符】:abc &lt;= 2 (大于等于)、abc &gt;= 2 (小于等于)

if 标签的示例(1):

1
2
3
4
5
6
7
8
9
10
11
12
<select id="findActiveBlogLike"
resultType="Blog">
select * from BLOG
where state = ‘ACTIVE’
<if test="title != null">
AND title like #{title}
</if>

<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</select>

if 标签的示例(2)-【可能因条件不成立而报错】:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<select id="findActiveBlogLike"
resultType="Blog">

// 条件不成立时:SELECT * FROM BLOG WHERE
SELECT * FROM BLOG
WHERE
<if test="state != null">
state = #{state}
</if>
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</select>

if 标签的示例(2)-【改进】:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG
<where>
<if test="state != null">
state = #{state}
</if>
<if test="title != null and title != ‘’ ">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</where>
</select>

4.2、choose-when-otherwise 标签:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG
WHERE state = ‘ACTIVE’
<choose>
<when test="title != null">
AND title like #{title}
</when>

<when test="author != null and author.name != null">
AND author_name like #{author.name}
</when>

<otherwise>
AND featured = 1
</otherwise>
</choose>
</select>

4.3、where 标签:

注意:该标签解决了可能因条件全部不成立而导致的 SQL语句问题,where标签只会去掉前面的and 或者 or,因此 SQL语句的and 要放开头。

and | or 写在前面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG
<where>
<if test="state != null">
state = #{state}
</if>
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</where>
</select>

4.4、trim标签:

trim 标签可以定制SQL语句,类似于where标签的功能【可解决:where标签只能去除前面的and | or的问题】

and | or 写在后面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 从where字符开始,如果标签内部的条件不成立,则去掉最终的SQL语句中多余的 and 或 or 字符    
// prefix: 给整条SQL语句拼接后的条件部分加一个前缀【相当于不写where关键字,而让前缀自动写where关键字】
// prefixOverrides: 可以去除哪种多余的连接符
// suffix: 加一个后缀
// suffixOverrides: 去掉拼接后的SQL语句后面多余的后缀
<trim prefix="where" prefixOverrides="and | or">
<if test="state != null">
<if test="state != null">
state = #{state}
</if>
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</trim>

4.5、set 标签

set 标签是用于 update 标签内部的,其作用类似与 update 语句的 set 子句。

1
2
3
4
5
6
7
8
9
10
<update id="updateAuthorIfNecessary">
update Author
<set>
<if test="username != null">username=#{username},</if>
<if test="password != null">password=#{password},</if>
<if test="email != null">email=#{email},</if>
<if test="bio != null">bio=#{bio}</if>
</set>
where id=#{id}
</update>

4.6、foreach 标签

foreach 标签,用于遍历某个数组、集合。

常用的属性:

  • item:当前元素
  • index:当前元素的迭代次数map集合的key
  • collcection:被迭代的数组、集合
  • open:数组、集合的开始分隔符
  • separator:数组、集合的中间分隔符
  • close:数组、集合的闭合分隔符
1
2
3
4
5
6
7
8
9
10
11
<select id="selectPostIn" resultType="domain.blog.Post">
SELECT *
FROM POST P
<where>
<foreach item="item" index="index" collection="list"
open="ID in (" separator="," close=")"
nullable="true">
#{item}
</foreach>
</where>
</select>

4.7、bind 标签

bind 标签:用于在 select 标签内部 设置模糊查询的条件。

使用 bind 标签的原因:不同的数据库使用模糊查询的语法不同

使用步骤:

  • 用于在 select 标签内部 拼接模糊查询的条件。
  • 在SQL语句中使用
1
2
3
4
5
6
7
8
9
<select id="selectBlogsLike" resultType="Blog">
// title为参数变量名,也可替换成 _parameter.getTitle()
<bind name="pattern" value="'%' + title + '%'" />

SELECT *
FROM BLOG
WHERE
title LIKE #{pattern}
</select>

4.8、两个内置的参数

  • _paramater:单个参数时,就是该参数;多个参数时,会封装为 map。
  • _databaseId:若在全局配置文件中设置了databaseProvider,则该内置参数代表当前数据库的别名。

5、Mybatis 缓存

5.1、一级缓存

Mybatis 中的SQL语句执行后会有缓存,再次执行相同的语句时,无需编译SQL语句,直接执行缓存中的SQL。

Mybatis 缓存包括了一级缓存二级缓存默认开启了一级缓存【一级缓存关不了】。

  • 一级缓存:是 SqlSession级别【查询缓存、本地缓存】的,每次进行增删改操作时,一级缓存失效。
  • 二级缓存:是 Mapper(dao)【namespace】级别【表级缓存、全局缓存】的,多个一级缓存可以共享同一个二级缓存 ,二级缓存是事务性的。

缓存-1

手动清理一级缓存:sqlSession.clearCache();

Mybatis的缓存在底层使用 Map封装。

一级缓存失效(不起作用)的四种情况:

  • SqlSession 不同。
  • SqlSession 相同,但查询条件不同
  • SqlSession 相同,查询条件相同,但执行了增删改操作。
  • SqlSession 相同,手动清除了一级缓存。

5.2、二级缓存

二级缓存默认是不开启的,需要手动开启二级缓存。

二级缓存的运行机制:

  • 一个SqlSession,查询数据后,数据保存到了一级缓存
  • 关闭SqlSession,一级缓存保存到了二级缓存,新的SqlSession就可以共享之前的数据。
  • 不同 namespace(dao)的数据会放在自己的的map里。

映射配置文件的每个增删改标签若使用了flushCache=“true”,则增删改操作执行后会清理缓存(一、二级全清理)

二级缓存的使用步骤:

  • JavaBean 可序列化
  • MyBatis 的全局配置文件中设置setting标签

(1)实现二级缓存的时候,MyBatis 要求返回的POJO必须是可序列化的。开启二级缓存的条件也是比较简单,通过直接在 MyBatis 的全局配置文件中(全局生效)通过:

1
2
3
<settings>
<setting name = "cacheEnabled" value = "true" />
</settings>

或在Mapper映射配置文件的select标签中使用useCache属性配置(单个语句生效)

(2)然后,dao接口的映射配置文件中通过<cache />标签:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.dao.DeptDao">

// eviction:清除策略,
// - LRU(默认):按使用频率移除,优先删除不常用的缓存
// - FIFO :按缓存产生时的顺序来删除
// - SOFT :按 GC的状态 和 软引用规则 来删除
// - WEAK :按 GC的状态 和 弱引用规则 来删除
// flushInterval: 缓存的刷新时间的间隔(毫秒),默认不清空
// size:缓存区的大小【“引用”的个数】,默认1024
// readOnly:
// - true:只读,不安全,速度快
// - false:缓存数据可能被修改,利用序列化和反序列化技术clone一份新的缓存
<cache
eviction="FIFO"
flushInterval="60000"
size="512"
readOnly="true"
/>
</mapper>

(3)最后,POJO实现序列化接口。

6、Mybatis 整合 Spring

所需的 JAR包:

  • spring-webmvc
  • spring-tx
  • spring-jdbc
  • aspectjweaver
  • junit
  • mysql-connector-java
  • druid
  • mybatis
  • mybatis-spring
  • lombok(使用注解@Data来代替Getter、setter等方法)

maven导入jar包:

pom.xml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
<?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.cyw</groupId>
<artifactId>SSM-02</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>

<name>SSM-02 Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>

<!--
=============================================================
-->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.7</version>
</dependency>

<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.9</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.14</version>
</dependency>
<dependency>
<groupId>org.singledog</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.3</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.0.4</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.9</version>
</dependency>

</dependencies>
<!--
=============================================================
-->
<build>
<finalName>SSM-02</finalName>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<testFailureIgnore>true</testFailureIgnore>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

6.1、整合的步骤:

1、编写:数据库(数据源)的配置:druid.properties

1
2
3
4
5
6
7
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/ssm01?useUnicode=true&characterEncoding=utf-8
user=root # 由于spring中${username}默认取的是系统的用户名,会覆盖掉配置文件的内容,所以改配置的属性名
pwd=root
initialSize=5
maxActive=100
maxWait=5000

2、编写:Spring 的全局配置文件:applicationContext.xml

2-1、引入命名空间和约束:

  • beans

  • context

  • aop

  • tx

applicationContext.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?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:aop="http://www.springframework.org/schema/aop"
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.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
">


</beans>

2-2、在applicationContext.xml中的beans标签内读取 数据库配置文件:

1
2
3

<context:property-placeholder location="classpath:conf/druid-conf.properties" />

2-3、在applicationContext.xml中的 开启组件扫件、AOP代理:

1
2
3
4
  // 扫描com.cyw包(包括子包)下的所有组件
<context:component-scan base-package="com.cyw"/>
<aop:aspectj-autoproxy/>

2-4、在applicationContext.xml中的 配置数据源:

1
2
3
4
5
6
7
8
9
10
11
<!--    配置数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<!--高版本的Driver可以自动识别数据库 而不再需要指定具体是哪一个Driver了-->
<property name="driverClassName" value="${driverClassName}" />
<property name="url" value="${url}" />
<property name="username" value="${user}" />
<property name="password" value="${password}" />
<property name="initialSize" value="1" />
<property name="maxActive" value="50" />
<property name="maxWait" value="30000" />
</bean>

2-5、在applicationContext.xml中的 配置事务管理器:

1
2
3
4
5
6
<!--    事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 基于注解的事务配置-->
<tx:annotation-driven transaction-manager="transactionManager"/>

2-6、在applicationContext.xml中的 配置Mybatis的sqlSessionFactory:

1
2
3
4
5
6
7
8
<!--    注册sqlSessionFactory:
- 数据源
- 配置Mybatis的全局配置文件的路径
-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:conf/mybatis-conf.xml"/>
</bean>

2-7、在applicationContext.xml中的 配置Dao接口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!--自动批量注册Dao接口(不写dao实现类的方式)-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.cyw.dao"/>
</bean>

<!--手动注册Dao接口(不写dao实现类的方式)-->
<!-- <bean id="stuDao" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="com.cyw.dao.StuDao"/>
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
<bean id="stuIdCardDao" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="com.cyw.dao.StuIdCardDao"/>
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
-->

3、编写:Mybatis 的全局配置文件:mybatis-conf.xml

1
2
3
4
5
6
7
8
9
10
11
12
<?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>

// 批量注册com.cyw.dao中的接口【可省略】
<mappers>
<package name="com.cyw.dao"/>
</mappers>

</configuration>

4、编写:Mybatis 的映射配置文件:StuMapper.xmlStuIdCardMapper.xmlClassesMapper.xml

注意:

  • mapper 标签的 namespace 属性的值为 Dao接口的全类名
  • 增删改查标签的 id 属性:为Dao接口的方法名
  • 增删改查标签的 parameterType 属性:为Dao接口的参数类型的别名或全类名
  • 增删改查标签的 resultMap 属性:为 resultMap标签的 id

StuMapper.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cyw.dao.StuDao">


// 结果集的(封装)映射规则
<resultMap id="UserRst" type="com.cyw.po.Stu">
<id property="id" column="id"/>
<result property="name" column="name" javaType="string"/>
<result property="sex" column="sex"/>
<!-- 嵌套结果(多表关联的语句在SQL里写)
<association property="card" javaType="com.cyw.po.StuIdCard">
<id property="id" column="id"/>
<result property="code" column="code" />
</association>
-->
// 嵌套查询,调用另一个接口的查询方法
<association property="card"
column="id"
javaType="com.cyw.po.StuIdCard"
select="com.cyw.dao.StuIdCardDao.getStuIdCardById"
/>

</resultMap>

<select id="getStuById"
parameterType="integer"
resultMap="UserRst">
<!-- 嵌套结果方式的SQL
select stu.*,stuIdCard.code
from stu,stuIdCard
where stu.id = #{id}
and stu.id = stuIdCard.id; -->

// 嵌套查询方式的SQL
select * from stu where id = #{id};
</select>

</mapper>

StuIdCardMapper.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cyw.dao.StuIdCardDao">

<select id="getStuIdCardById"
parameterType="integer"
resultType="com.cyw.po.StuIdCard">
select * from stuIdCard where id = #{id};
</select>

</mapper>

6.2、目录结构及配置文件:

image-20220130110933244

Spring的配置文件(mybatis的配置文件见上面的“整合步骤”小节):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<?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:aop="http://www.springframework.org/schema/aop"
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/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
">

<context:component-scan base-package="com.cyw"/>
<aop:aspectj-autoproxy/>

<context:property-placeholder location="classpath:conf/druid-conf.properties" />

<!-- 配置数据源-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<!--高版本的Driver可以自动识别数据库 而不再需要指定具体是哪一个Driver了-->
<property name="driverClassName" value="${driverClassName}" />
<property name="url" value="${url}" />
<property name="username" value="${user}" />
<property name="password" value="${password}" />
<property name="initialSize" value="1" />
<property name="maxActive" value="50" />
<property name="maxWait" value="30000" />
</bean>

<!-- 事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 基于注解的事务配置-->
<tx:annotation-driven transaction-manager="transactionManager"/>


<!-- 注册sqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:conf/mybatis-conf.xml"/>
</bean>


<!--手动注册Dao接口(不写dao实现类的方式)-->
<!-- <bean id="stuDao" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="com.cyw.dao.StuDao"/>
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
<bean id="stuIdCardDao" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="com.cyw.dao.StuIdCardDao"/>
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
-->
<!--自动注册Dao接口(不写dao实现类的方式)-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.cyw.dao"/>
</bean>


</beans>

7、Mybatis 逆向工程

Mybatis 逆向工程是什么?

Mybatis 逆向工程(MyBatis Generator)也叫 MBG,可以通过逆向工程的配置文件自动生成 POJO(JavaBean)、Dao、Dao的映射配置文件。

使用步骤:

1、maven 项目在 pom.xml 文件中添加以下代码:

1
2
3
4
5
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.4.0</version>
</dependency>

2、在项目中创建MGB的配置文件(名字随便起,此处命名为genertorConfig.xml ):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<?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>
<context id="DB2Tables" targetRuntime="MyBatis3">
<commentGenerator>
<!-- 是否去除自动生成的注释 -->
<property name="suppressAllComments" value="true" />
</commentGenerator>
<!-- Mysql数据库连接的信息:驱动类、连接地址、用户名、密码 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/test"
userId="root"
password="root" />

<!-- 默认为false,把JDBC DECIMAL 和NUMERIC类型解析为Integer,为true时 把JDBC DECIMAL 和NUMERIC类型解析为java.math.BigDecimal -->
<javaTypeResolver>
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>

<!-- targetProject:生成POJO类的位置 -->
<javaModelGenerator
targetPackage="net.biancheng.pojo" targetProject=".\src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
<!-- 从数据库返回的值被清理前后的空格 -->
<property name="trimStrings" value="true" />
</javaModelGenerator>

<!-- targetProject:mapper映射文件生成的位置 -->
<sqlMapGenerator targetPackage="net.biancheng.mapper"
targetProject=".\src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
</sqlMapGenerator>

<!-- targetProject:mapper接口生成的的位置 -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="net.biancheng.mapper" targetProject=".\src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
</javaClientGenerator>

<!-- 指定数据表 -->
<table tableName="website"></table>
<table tableName="student"></table>
<table tableName="studentcard"></table>
<table tableName="user"></table>
</context>

</generatorConfiguration>

3、创建执行MBG 的类,来自动生成 POJO、Dao接口、Dao的映射配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package net.biancheng;

import java.io.File;
import java.util.*;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;

public class GeneratorSqlmap {
public void generator() throws Exception {
//
List<String> warnings = new ArrayList<String>();
boolean overwrite = true;

// 指定配置文件
File configFile = new File("./config/generatorConfig.xml");

// 创建解析器
ConfigurationParser cp = new ConfigurationParser(warnings);

// 读取配置
Configuration config = cp.parseConfiguration(configFile);

//
DefaultShellCallback callback = new DefaultShellCallback(overwrite);

// 创建MGB生成器
MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);

// 生成
myBatisGenerator.generate(null);

}

// 执行main方法以生成代码
public static void main(String[] args) {
try {
GeneratorSqlmap generatorSqlmap = new GeneratorSqlmap();
generatorSqlmap.generator();
} catch (Exception e) {
e.printStackTrace();
}
}
}

8、Mybatis 运行原理


9、Mybatis 插件


10、Mybatis 扩展