开发环境

  • porm.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
<?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.cuc.mybatis</groupId>
<artifactId>MyBatis_demo1</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>

<dependencies>
<!-- Mybatis核心 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<!-- junit测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.3</version>
</dependency>
<!-- log4j日志 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>

</project>
  • 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
66
67
68
69
70
71
72
<?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>

<!--
MyBatis核心配置文件中标签的配置顺序
properties,settings,typeAliases,typeHandlers,
objectFactory,objectWrapperFactory,reflectorFactory,
plugins,environments,databaseIdProvider,mappers
-->

<!--引入properties文件-->
<properties resource="jdbc.properties" />

<!--设置类型别名
注意:类型别名不区分大小写
-->
<typeAliases>
<!--alias:类型别名,可以不写,默认就是User-->
<!--<typeAlias type="com.cuc.mybatis.pojo.User" alias="User" />-->

<!--以包为单位,将包内所有类型设置别名-->
<package name="com.cuc.mybatis.pojo"/>
</typeAliases>

<!--
environments:配置多个连接数据库的环境
属性default:设置默认使用环境的id
-->
<environments default="development">
<!--
配置某个具体环境
属性id:数据库环境的唯一标识
-->
<environment id="development">
<!--
transactionManager:设置事务管理方式
属性type:JDBC 、 MANAGED
JDBC:表示当前环境中,执行SQL时,使用的是JDBC原生的事务管理方式(事务的提交或回滚需要手动处理)
MANAGED:被管理,例如Spring
-->
<transactionManager type="JDBC"/>
<!--
dataSource:配置数据源
属性type:设置数据源类型
POOLED:使用数据库连接池缓存数据库连接
UNPOOLED:表示使用数据库连接池
JNDI:使用上下文中的数据源
-->
<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="mappers/UserMapper.xml"/>-->

<!--
以包为单位引入映射文件
要求:
1、mapper接口所在的包要和映射文件所在的包一致
2、mapper接口要和映射文件的名字一致
-->
<package name="com.cuc.mybatis.mapper"/>
</mappers>
</configuration>
  • jdbc.properties
1
2
3
4
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8
jdbc.username=root
jdbc.password=root

项目结构

1
2
3
4
5
6
7
8
9
10
11
main
├── java
└── com.cuc.mybatis
└── mapper
└── pojo
├── resources
└── com.cuc.mybatis
└── mapper
└── jdbc.properties
└── mybatis-config.xml
└── log4j.xml

HelloWorld

  • 添加测试
1
2
3
4
<!--int insertUser();-->
<insert id="insertUser">
insert into t_user values(null,'刘一','123',23,'女','123@qq.com')
</insert>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Test
public void testInsert() throws IOException {
// 加载核心配置文件
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
// 获取SqlSessionFactoryBuilder
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 获取SqlSessionFactory
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
// 获取SqlSession (true自动提交事务,不写则不自动提交事务,需要写下面提交事务代码)
SqlSession sqlSession = sqlSessionFactory.openSession(true);
// 获取mapper接口对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
int result = userMapper.insertUser();
// 提交事务
// sqlSession.commit();

System.out.println("受影响的行数:"+result);
}
  • 其它测试
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
<!--int insertUser();-->
<insert id="insertUser">
insert into t_user values(null,'刘一','123',23,'女','123@qq.com')
</insert>
<!--int updateUser();-->
<update id="updateUser">
update t_user set username='张三',sex='男' where id = 5
</update>
<!--int deleteUser();-->
<delete id="deleteUser">
delete from t_user where id > 5
</delete>
<!--User getUserById();-->
<!--
查询功能必须设置resultType 或 resultMap
resultType:设置默认的映射关系
resultMap:设置自定义的映射关系
-->
<select id="getUserById" resultType="user">
select * from t_user where id = 4
</select>
<!--List<User> getAllUser();-->
<select id="getAllUser" resultType="User">
select * from t_user
</select>

封装SqlSessionUtil工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class SqlSessionUtil {

public static SqlSession getSqlSession() {
SqlSession sqlSession = null;
try {
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
sqlSession = sqlSessionFactory.openSession(true);
} catch (IOException e) {
e.printStackTrace();
}
return sqlSession;
}
}

获取参数值

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
<!--User getUserByUsername(String username);-->
<select id="getUserByUsername" resultType="User">
<!--#{} 里面的名称不固定,因为是根据位置获取参数值,而不是参数名-->
<!--select * from t_user where username = #{username}-->

<!--${} 里面的名称同样可以更改-->
select * from t_user where username = '${username}'
</select>

<!--User getUserByUsernameAndPassword(String username,String password);-->
<!--arg0,arg1 以及 param1,param2 都可以获取参数值,注意下标,可以混着用-->
<select id="getUserByUsernameAndPassword" resultType="User">
<!--select * from t_user where username = #{arg0} and password = #{arg1}-->
select * from t_user where username = '${param1}' and password = '${param2}'
</select>

<!--User getUserByMap(Map<String,Object> map);-->
<select id="getUserByMap" resultType="User">
<!--select * from t_user where username = #{username} and password = #{password}-->
select * from t_user where username = '${username}' and password = '${password}'
</select>

<!--int addUser(User user);-->
<insert id="addUser">
<!--insert into t_user values (null,#{username},#{password},#{age},#{sex},#{email})-->
insert into t_user values (null,'${username}','${password}','${age}','${sex}','${email}')
</insert>

<!--User getUserByParam(@Param("username") String username,@Param("password") String password);-->
<select id="getUserByParam" resultType="User">
<!--select * from t_user where username = #{username} and password = #{password}-->
select * from t_user where username = '${username}' and password = '${password}'
</select>
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
public class ParameterMapperTest {

/**
* MyBatis获取参数值的两种方式 ${} 和 #{}
* ${} 字符串拼接
* #{} 占位符赋值
*
* MyBatis获取参数值的各种情况:
* 1、mapper接口方法的参数为单个字面量类型
* 可以通过 ${} 、 #{} 以任意的名称获取参数值
* 2、mapper接口方法参数为多个时
* 此时MyBatis会将这些参数放在一个map集合中,以两种方式进行存储
* a--> 以arg0,arg1...为键,以参数为值
* b--> 以param1,param2...为键,以参数为值
* 3、若mapper接口参数有多个时,可以手动将这些参数放在一个map中存储
* 只需要以自定义键名称访问参数值即可
* 4、mapper接口参数是实体类类型的参数
* 只需要以属性名称访问值即可,需要注意的是,它是根据get方法取值的,而不是看类中有没有对应属性
* 5、使用@Param注解命名参数
* 此时MyBatis会将这些参数放在一个map集合中,以两种方式进行存储
* a--> 以@Param注解定义的值为键,以参数为值
* b--> 以param1,param2...为键,以参数为值
*/

@Test
public void testGetUserByUsername() {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
ParameterMapper parameterMapper = sqlSession.getMapper(ParameterMapper.class);
User user = parameterMapper.getUserByUsername("张三");
System.out.println(user.toString());
}

@Test
public void testGetUserByUsernameAndPassword() {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
ParameterMapper parameterMapper = sqlSession.getMapper(ParameterMapper.class);
User user = parameterMapper.getUserByUsernameAndPassword("张三","123");
System.out.println(user.toString());
}

@Test
public void testGetUserByMap() {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
ParameterMapper parameterMapper = sqlSession.getMapper(ParameterMapper.class);
Map<String,Object> map = new HashMap<>();
map.put("username","张三");
map.put("password","123");
User user = parameterMapper.getUserByMap(map);
System.out.println(user.toString());
}

@Test
public void testAddUser() {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
ParameterMapper parameterMapper = sqlSession.getMapper(ParameterMapper.class);
User user = new User(null,"王五","123",20,"女","111@qq.com");
int result = parameterMapper.addUser(user);
System.out.println("受影响的行数:"+result);
}

@Test
public void testGetUserByParam() {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
ParameterMapper parameterMapper = sqlSession.getMapper(ParameterMapper.class);
User user = parameterMapper.getUserByParam("张三","123");
System.out.println(user.toString());
}
}

各种查询

通用SQL

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!--User getUserById(@Param("id") Integer id);-->
<select id="getUserById" resultType="User">
select * from t_user where id = #{id}
</select>

<!--Map<String,Object> getUserByIdToMap(@Param("id") Integer id);-->
<select id="getUserByIdToMap" resultType="Map">
select * from t_user where id = #{id}
</select>

<!--List<User> getAllUser();-->
<select id="getAllUser" resultType="User">
select * from t_user
</select>

<!--List<Map<String,Object>> getAllUserToMap();-->
<select id="getAllUserToMap" resultType="Map">
select * from t_user
</select>

<!--int getCount();-->
<select id="getCount" resultType="Integer">
select count(*) from t_user
</select>

@MapKey

在上面getAllUserToMap()也可以这样实现

1
2
@MapKey("id") // 将id字段值设为key
Map<String,Object> getAllUserToMap();
1
2
3
4
<!--Map<String,Object> getAllUserToMap();-->
<select id="getAllUserToMap" resultType="Map">
select * from t_user
</select>

image-20220705040607243

特殊SQL

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
<!--List<User> getUserByLike(@Param("username") String username);-->
<select id="getUserByLike" resultType="User">
<!--select * from t_user where username like '%${username}%'-->
<!--select * from t_user where username like concat('%',#{username},'%')-->
select * from t_user where username like "%"#{username}"%"
</select>

<!--int deleteMore(@Param("ids") String ids);-->
<delete id="deleteMore">
delete from t_user where id in (${ids})
</delete>

<!--List<User> getUsersByTableName(@Param("tableName") String tableName);-->
<select id="getUsersByTableName" resultType="User">
select * from ${tableName}
</select>

<!--int insertUser(User user);-->
<!--
useGeneratedKeys:设置当前标签中的sql使用了自增的主键
keyProperty:将自增主键的值赋值给传输到映射文件中参数的某个属性
-->
<insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
insert into t_user values (null,#{username},#{password},#{age},#{sex},#{email})
</insert>
1
2
3
4
5
6
7
8
@Test
public void testInsertUser(){
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
SQLMapper sqlMapper = sqlSession.getMapper(SQLMapper.class);
User user = new User(null,"李四","123",11,"女","123@qq.com");
sqlMapper.insertUser(user);
System.out.println(user); // 这时user的id属性不为null,而是自动递增后的值
}

解决字段名跟属性名不一致

问题

Emp的属性empName与查询的字段emp_name不一致时,结果Emp的属性empName为空。

1
2
3
4
5
<!--List<Emp> getAllEmp();-->
<select id="getAllEmp" resultType="Emp">
<!--select eid,emp_name,age,sex,email from t_emp-->
select * from t_emp
</select>

列起别名

1
2
3
4
5
<!--List<Emp> getAllEmp();-->
<select id="getAllEmp" resultType="Emp">
<!--select eid,emp_name empName,age,sex,email from t_emp-->
select * from t_emp
</select>

mybatis全局配置

1
2
3
4
5
<!--设置MyBatis的全局配置-->
<settings>
<!--自动将字段名下划线映射成驼峰形式 eg:emp_name: empName -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

使用resultMap

1
2
3
4
5
6
7
8
9
10
11
<!--id:主键映射关系,result:普通属性映射关系-->
<resultMap id="empResultMap" type="Emp">
<id property="eid" column="eid" />
<result property="empName" column="emp_name" />
<result property="age" column="age" />
<result property="sex" column="sex" />
<result property="email" column="email" />
</resultMap>
<select id="getAllEmp" resultMap="empResultMap">
select * from t_emp
</select>

处理多对一映射关系

级联赋值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!--方式一:级联解决多对一映射关系-->
<resultMap id="EmpAndDeptResultMapOne" type="Emp">
<id property="eid" column="eid" />
<result property="empName" column="emp_name" />
<result property="age" column="age" />
<result property="sex" column="sex" />
<result property="email" column="email" />
<result property="dept.did" column="did" />
<result property="dept.deptName" column="dept_name" />
</resultMap>
<!--Emp getEmpAndDept(int eid);-->
<select id="getEmpAndDept" resultMap="EmpAndDeptResultMapOne">
select * from t_emp left join t_dept on t_emp.did = t_dept.did where t_emp.eid = #{eid}
</select>

assosiation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!--方式二:association解决多对一映射关系-->
<resultMap id="EmpAndDeptResultMapTwo" type="Emp">
<id property="eid" column="eid" />
<result property="empName" column="emp_name" />
<result property="age" column="age" />
<result property="sex" column="sex" />
<result property="email" column="email" />
<association property="dept" javaType="Dept">
<id property="did" column="did" />
<result property="deptName" column="dept_name" />
</association>
</resultMap>
<!--Emp getEmpAndDept(int eid);-->
<select id="getEmpAndDept" resultMap="EmpAndDeptResultMapTwo">
select * from t_emp left join t_dept on t_emp.did = t_dept.did where t_emp.eid = #{eid}
</select>

分步查询

DeptMapper.xml

1
2
3
4
<!--Dept getEmpAndDeptStepTwo(@Param("did") int did);-->
<select id="getEmpAndDeptStepTwo" resultType="Dept">
select * from t_dept where did = #{did}
</select>

EmpMapper.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!--方式三:分步解决多对一映射关系-->
<resultMap id="EmpAndDeptStep" type="Emp">
<id property="eid" column="eid" />
<result property="empName" column="emp_name" />
<result property="age" column="age" />
<result property="sex" column="sex" />
<result property="email" column="email" />
<!--当前配置文件中设置了延迟加载,之后可以通过fetchType属性设置某个查询是否需要延迟加载,eager代表立即加载,lazy代表延迟加载-->
<association property="dept" select="com.cuc.mybatis.mapper.DeptMapper.getEmpAndDeptStepTwo" column="did" fetchType="lazy"/>
</resultMap>
<!--Emp getEmpAndDeptStepOne(@Param("eid") int eid);-->
<select id="getEmpAndDeptStepOne" resultMap="EmpAndDeptStep">
select * from t_emp where eid = #{eid}
</select>

延迟加载

适用于分步查询。

lazyLoadingEnabled:开启时,所有关联对象都会延迟加载。

相当于按需加载,需要获取的数据是什么,就只会执行相应的sql。此时可以通过associationcollectionfetchType属性设置当前分步查询是否使用延迟加载,fetchType=”lazy”(延迟加载)| fetchType=”eager”(立即加载)

1
2
3
4
5
<!--设置MyBatis的全局配置-->
<settings>
<!--开启延迟加载-->
<setting name="lazyLoadingEnabled" value="true"/>
</settings>
1
2
3
4
5
// 测试延迟加载功能
// 只执行能获取到empName的语句
System.out.println(empMapper.getEmpAndDeptStepOne(1).getEmpName());
// 只执行能获取到dept的语句
System.out.println(empMapper.getEmpAndDeptStepOne(1).getDept());

处理一对多映射关系

collection

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<resultMap id="DeptAndEmp" type="Dept">
<id property="did" column="did" />
<result property="deptName" column="dept_name" />
<!--
collection:用来处理一对多映射关系
ofType:该属性所对应的集合中存储数据的类型
-->
<collection property="emps" ofType="Emp">
<id property="eid" column="eid" />
<result property="empName" column="emp_name" />
<result property="age" column="age" />
<result property="sex" column="sex" />
<result property="email" column="email" />
</collection>
</resultMap>
<!--Dept getDeptAndEmp(@Param("did") int did);-->
<select id="getDeptAndEmp" resultMap="DeptAndEmp">
select * from t_dept left join t_emp on t_dept.did = t_emp.did where t_dept.did = #{did}
</select>

分步查询

EmpMapper.xml

1
2
3
4
<!--List<Emp> getDeptAndEmpStepTwo(@Param("did") int did);-->
<select id="getDeptAndEmpStepTwo" resultType="Emp">
select * from t_emp where did = #{did}
</select>

DeptMapper.xml

1
2
3
4
5
6
7
8
9
<resultMap id="DeptAndEmpStepOne" type="Dept">
<id property="did" column="did" />
<result property="deptName" column="dept_name" />
<collection property="emps" select="com.cuc.mybatis.mapper.EmpMapper.getDeptAndEmpStepTwo" column="did" />
</resultMap>
<!--Dept getDeptAndEmpStepOne(@Param("did") int did);-->
<select id="getDeptAndEmpStepOne" resultMap="DeptAndEmpStepOne">
select * from t_dept where did = #{did}
</select>

动态SQL

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
<!--List<Emp> getEmpByCondition(Emp emp);-->
<select id="getEmpByCondition" resultType="Emp">
select * from t_emp where 1=1
<if test="empName != null and empName != ''">
and emp_name = #{empName}
</if>
<if test="age != null and age != ''">
and age = #{age}
</if>
<if test="sex != null and sex != ''">
and sex = #{sex}
</if>
<if test="email != null and email != ''">
and email = #{email}
</if>
</select>

<!--List<Emp> getEmpByConditionTwo(Emp emp);-->
<!--
where标签:可以将语句前面多余的 and 或 or 去掉
注意:where标签不能把后面的and or 去掉,例如emp_name = #{empName} and
-->
<select id="getEmpByConditionTwo" resultType="Emp">
select * from t_emp
<where>
<if test="empName != null and empName != ''">
and emp_name = #{empName}
</if>
<if test="age != null and age != ''">
and age = #{age}
</if>
<if test="sex != null and sex != ''">
or sex = #{sex}
</if>
<if test="email != null and email != ''">
and email = #{email}
</if>
</where>
</select>

<!--sql标签-->
<sql id="empColumns">eid,emp_name,age,sex,email</sql>

<!--List<Emp> getEmpByConditionThree(Emp emp);-->
<!--
trim属性:
prefix|suffix:向trim标签中内容前面/后面添加指定内容
prefixOverrides|suffixOverrides:向trim标签中内容前面/后面去除指定内容
-->
<select id="getEmpByConditionThree" resultType="Emp">
select <include refid="empColumns" /> from t_emp
<trim prefix="where" suffixOverrides="and|or">
<if test="empName != null and empName != ''">
emp_name = #{empName} and
</if>
<if test="age != null and age != ''">
age = #{age} or
</if>
<if test="sex != null and sex != ''">
sex = #{sex} and
</if>
<if test="email != null and email != ''">
email = #{email}
</if>
</trim>
</select>

<!--List<Emp> getEmpByChoose(Emp emp);-->
<!--choose、when、otherwise相当于if...else if...else-->
<select id="getEmpByChoose" resultType="Emp">
select * from t_emp
<where>
<choose>
<when test="empName!=null and empName!=''">
emp_name = #{empName}
</when>
<when test="age!=null and age!=''">
age = #{age}
</when>
<when test="sex!=null and sex!=''">
sex = #{sex}
</when>
<otherwise>
did = 1
</otherwise>
</choose>
</where>
</select>

<!--int deleteMoreByArray(@Param("eids") Integer[] eids);-->
<!--separator:分隔符 open|close:表示循环以什么开始以什么结束-->
<delete id="deleteMoreByArray">
<!--delete from t_emp where eid in-->
<!-- <foreach collection="eids" item="eid" separator="," open="(" close=")">-->
<!-- #{eid}-->
<!-- </foreach>-->
delete from t_emp where
<foreach collection="eids" item="eid" separator="or">
eid = #{eid}
</foreach>
</delete>

<!--int insertMoreByList(@Param("emps") List<Emp> emps);-->
<insert id="insertMoreByList">
insert into t_emp values
<foreach collection="emps" item="emp" separator=",">
(null,#{emp.empName},#{emp.age},#{emp.sex},#{emp.email},null)
</foreach>
</insert>

一级缓存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
* 一级缓存(单个SqlSession级别):默认开启
* 一级缓存失效的情况:
* 1、不同sqlSession对应不同的一级缓存
* 2、同一个sqlSession但是查询条件不同
* 3、同一个sqlSession两次查询期间执行了任何一次增删改操作
* 4、同一个sqlSession两次查询期间手动清空了缓存
*/

@Test
public void testGetEmpByEid(){
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
CacheMapper cacheMapper1 = sqlSession.getMapper(CacheMapper.class);
System.out.println(cacheMapper1.getEmpByEid(1));

// sqlSession.clearCache(); // 清空缓存
CacheMapper cacheMapper2 = sqlSession.getMapper(CacheMapper.class);
System.out.println(cacheMapper2.getEmpByEid(1));
}

二级缓存

1
2
3
4
5
6
7
<!--开启二级缓存-->
<cache />

<!--Emp getEmpByEid(@Param("eid") int eid);-->
<select id="getEmpByEid" resultType="Emp">
select * from t_emp where eid = #{eid}
</select>
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
/**
* 二级缓存(SqlSessionFactory级别):需手动开启
* 工厂可以管理多个sqlSession,即将级别提高到同一个工厂的sqlSession
* 1. 在核心配置文件中,设置全局配置属性cacheEnabled="true",默认为true,不需要设置
* 2. 在映射文件中设置标签<cache />
* 3. 二级缓存必须在SqlSession关闭或提交之后有效
* 4. 查询的数据所转换的实体类类型必须实现序列化的接口
* 失效情况:两次查询之间执行了任意的增删改,会使一级和二级缓存同时失效
*/

@Test
public void testGetEmpByEid2() throws IOException {
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(is);

SqlSession sqlSession1 = sqlSessionFactory.openSession(true);
SqlSession sqlSession2 = sqlSessionFactory.openSession(true);

CacheMapper cacheMapper1 = sqlSession1.getMapper(CacheMapper.class);
System.out.println(cacheMapper1.getEmpByEid(1));
sqlSession1.close();

CacheMapper cacheMapper2 = sqlSession2.getMapper(CacheMapper.class);
System.out.println(cacheMapper2.getEmpByEid(1));
sqlSession2.close();
}

逆向工程

正向工程:先创建Java实体类,有框架负责根据实体类生成数据库表。Hibernate支持正向工程

逆向工程:先创建数据库表,由框架负责根据数据库表,反向生成Java、Mapper接口、Mapper映射文件

1)依赖和插件

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
<!-- 控制Maven在构建过程中相关配置 -->
<build>
<!-- 构建过程中用到的插件 -->
<plugins>
<!-- 具体插件,逆向工程的操作是以构建过程中插件形式出现的 -->
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.0</version>
<!-- 插件的依赖 -->
<dependencies>
<!-- 逆向工程的核心依赖 -->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.2</version>
</dependency>
<!-- 数据库连接池 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.2</version>
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.3</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>

2)配置generatorConfig.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
<?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>
<!--
targetRuntime: 执行生成的逆向工程的版本
MyBatis3Simple: 生成基本的CRUD(清新简洁版)
MyBatis3: 生成带条件的CRUD(奢华尊享版)
-->
<context id="DB2Tables" targetRuntime="MyBatis3">
<!-- 数据库的连接信息 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf-8"
userId="root"
password="root">
</jdbcConnection>
<!-- javaBean的生成策略-->
<javaModelGenerator targetPackage="com.cuc.mybatis.pojo" targetProject=".\src\main\java">
<property name="enableSubPackages" value="true" />
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- SQL映射文件的生成策略 -->
<sqlMapGenerator targetPackage="com.cuc.mybatis.mapper"
targetProject=".\src\main\resources">
<property name="enableSubPackages" value="true" />
</sqlMapGenerator>
<!-- Mapper接口的生成策略 -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.cuc.mybatis.mapper" targetProject=".\src\main\java">
<property name="enableSubPackages" value="true" />
</javaClientGenerator>
<!-- 逆向分析的表 -->
<!-- tableName设置为*号,可以对应所有表,此时不写domainObjectName -->
<!-- domainObjectName属性指定生成出来的实体类的类名 -->
<table tableName="t_emp" domainObjectName="Emp"/>
<table tableName="t_dept" domainObjectName="Dept"/>
</context>
</generatorConfiguration>

3)双击

image-20220705203926682

4)使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Test
public void testMBG(){
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
// 查询所有数据
// List<Emp> emps = empMapper.selectByExample(null);
// emps.forEach(emp -> System.out.println(emp));

// 根据条件查询
// EmpExample example = new EmpExample();
// example.createCriteria().andEmpNameEqualTo("张三").andAgeEqualTo(15);
// example.or().andDidIsNotNull();
// List<Emp> emps = empMapper.selectByExample(example);
// emps.forEach(emp -> System.out.println(emp));

// 普通修改,如果给某个字段设置了null值,则数据库相应的字段值也变成null值
empMapper.updateByPrimaryKey(new Emp(1,"张三",20,"女","222@qq.com",1));

// 选择性修改,即为设置为null的字段不改变值,保留原来的值
empMapper.updateByPrimaryKeySelective(new Emp(1,"张三",20,null,"222@qq.com",1));
}

分页插件

1)依赖

1
2
3
4
5
6
<!--分页插件依赖-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.2.0</version>
</dependency>

2)配置mybatis配置文件

1
2
3
4
<plugins>
<!--设置分页插件-->
<plugin interceptor="com.github.pagehelper.PageInterceptor" />
</plugins>

3)使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* limit index,pageSize
* index:当前页的起始索引
* pageSize:每页显示条数
* pageNum:当前页页码
* index = (pageNum-1)* pageSize
*/

@Test
public void testPageHelper(){
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
EmpMapper empMapper = sqlSession.getMapper(EmpMapper.class);
// 在查询之前设置传入当前页码以及每页条数
// Page<Object> page = PageHelper.startPage(1,4);
PageHelper.startPage(1,4);
List<Emp> list = empMapper.selectByExample(null);
PageInfo<Emp> page = new PageInfo<>(list,5); // 5代表导航栏的页码数
System.out.println(page);
// list.forEach(emp -> System.out.println(emp.toString()));
}

image-20220705205307243