MyBatis基础知识点

1.基础配置

1.添加依赖包
1
2
3
4
5
6
7
8
9
10
11
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.1</version>
</dependency>
2.配置log4j

在 resources 目录下增加文件 log4j.properties

1
2
3
4
log4j.rootLogger=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
3.自定义model (POJO类)
4.MyBatis 的全局配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?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://127.0.0.1:3306/blog_db?useUnicode=true&amp;characterEncoding=utf8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</dataSource>
</environment>
</environments>
<!-- 映射文件配置 -->
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
</configuration>
5.自定义映射接口

此接口对应映射配置中的sql语句 实现sql转对象 对象转sql

1
2
3
4
public interface UserMapper {
//根据id获取用户信息
User findById(Long id);
}
6.编写XML映射文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?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="mapper.UserMapper">
<!-- findById对应接口中的方法 -->
<select id="findById" parameterType="java.lang.Long" resultType="bean.User">
select * from blog_db.user where id=#{id}
</select>
</mapper>

注释:
id 对应 接口中的方法名
parameterType : sql语句中参数的类型
resultType :返回结果类型
#{id} : 占位
7.主函数调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Main {
public static void main(String[] args) throws Exception{
// 1.新建session工厂构建类
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
// 2.session工厂构建类 读取配置文件构造 session工厂
SqlSessionFactory sessionFactory = sqlSessionFactoryBuilder.build(
Resources.getResourceAsReader("mybatis-config.xml"),
"development" // 这个参数可以省略,因为 mybatis-config.xml 的<environments>标签指定了默认环境为development
);
// 3.会话工厂 构建 会话
SqlSession sqlSession = sessionFactory.openSession();
// 4.调用session的操作数据库的一个操作
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.findById(1L);
System.out.println(user);
// 5.关闭会话
sqlSession.close();
}
}

基本使用结束—————————————-

1.使class的字段与sql中不一致的字段 一一对应

1
2
3
4
5
6
7
8
9
10
11
12
方案一  新建map规则:
<!-- 此处将User对象的username与sql的name对应 -->
<resultMap id="userResult" type="bean.User">
<result property="username" column="name" javaType="String" jdbcType="VARCHAR"/>
</resultMap>
<!-- 此处遵循userResult的映射规则 -->
<select id="findById" parameterType="Long" resultMap="userResult" resultType="bean.User">
select * from blog_db.user where id=#{id}
</select>

方案二 修改查询语句使符合字段:
select id, name AS username, email, password from blog_db.user where id=#{id}

2.多参数查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
方案一: 使用默认的param*占位
在接口中配置:
User findUserByNameAndPassWd(String name,String passwd);
在xml中配置:
<select id="findUserByNameAndPassWd" resultType="model.User">
select * from blog_db.user where name=#{param1} and password=#{param2}
</select>

方案二:使用注解注入参数名 使用参数占位
在接口中配置:
User findUserByNameAndPassWd2(@Param("name") String name, @Param("passwd") String passwd);
在xml中配置:
<select id="findUserByNameAndPassWd2" resultType="model.User">
select * from blog_db.user where name=#{name} and password=#{passwd}
</select>

3.Sort的小细节

1
2
3
4
排序的参数不能使用#{} 只能用${}
<select id="TestSort" resultType="model.User">
select * from blog_db.user order by ${orderRule} desc
</select>

4.事务:

1
2
3
4
5
6
7
8
得到一个数据库的操作对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
然后进行操作:
对于insert delete 和 update 需要有手动提交事务
userMapper.xxx(操作)
sqlSession.rollback(true); // 强制回滚
sqlSession.commit(); //提交
sqlSession.commit(true); // 强制提交

5.动态Sql

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
如果该字段不为空就加入where中进行比较
<select id="find" resultType="model.User" parameterType="model.User">
select * from blog_db.user
<where>
<if test=" id != null">
and id = #{id}
</if>
<if test="name != null">
and name = #{name}
</if>
<if test="email != null">
and email = #{email}
</if>
<if test="password != null">
and password = #{password}
</if>
</where>
</select>

6.一对一和一对多连表查询 返回混合值

  1. 使用扩展类,存储返回的数据 (一对一)
  2. 模型里有模型 (一对一)
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
<resultMap id="blogResult" type="bean.Blog">
<result property="id" column="blog_id"/>
<result property="ownerId" column="user_id"/>
<result property="title" column="blog_title"/>
<result property="content" column="blog_content"/>
<!--模型里有模型 association-->
<association property="user" javaType="bean.User">
<id property="id" column="user_id"/>
<result property="name" column="user_name"/>
<result property="email" column="user_email"/>
<result property="password" column="user_password"/>
</association>

</resultMap>

<select id="findById" parameterType="Long" resultMap="blogResult" resultType="bean.Blog">
SELECT
blog.id AS blog_id,
blog.title AS blog_title,
blog.content AS blog_content,
user.id AS user_id,
user.name AS user_name,
user.email AS user_email,
user.password AS user_password
FROM blog, user
WHERE
blog.id = #{id}
AND user.id=blog.owner_id;
</select>

3. 模型里有集合 (一对多)

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
    <!--首先创建map映射关系-->
<resultMap id="userResult" type="model.User">
<result property="id" column="user_id"/>
<result property="name" column="user_name"/>
<result property="email" column="user_email"/>
<result property="password" column="user_password"/>

<!--result里有集合 collection-->
<collection property="blogs" ofType="model.Blog">
<id property="id" column="blog_id"/>
<result property="ownerId" column="user_id"/>
<result property="title" column="blog_title"/>
<result property="content" column="blog_content"/>
</collection>
</resultMap>

<select id="findById" parameterType="Long" resultMap="userResult" resultType="model.User">
SELECT
user.id AS user_id,
user.name AS user_name,
user.email AS user_email,
user.password AS user_password,
blog.id AS blog_id,
blog.title AS blog_title,
blog.content AS blog_content
FROM user, blog
WHERE
user.id = 1
AND user.id=blog.owner_id;
</select>

7.两个表的查询关联

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
这个mapper是BlogMapper的xml配置
记得将改xml 注入 全局配置中
<mapper namespace="mapper.BlogMapper">
<!--联合多表查询-->
<!--首先要有两个表的map关系-->
<resultMap id="blogResult" type="model.Blog">
<result property="id" column="blog_id"/>
<result property="ownerId" column="user_id"/>
<result property="title" column="blog_title"/>
<result property="content" column="blog_content"/>

<association property="user"
javaType="model.User"
select="findOwnerOfBlog"
column="user_id" />

</resultMap>

<resultMap id="userResult" type="model.User">
<result property="id" column="user_id"/>
<result property="name" column="user_name"/>
<result property="email" column="user_email"/>
<result property="password" column="user_password"/>
</resultMap>

<!--两个查询-->
<select id="findById" parameterType="Long" resultMap="blogResult" resultType="model.Blog">
SELECT
id AS blog_id,
id AS user_id,
title AS blog_title,
content AS blog_content
FROM
blog
WHERE
id = #{id};
</select>

<select id="findOwnerOfBlog" parameterType="int" resultMap="userResult" resultType="model.User">
SELECT
id user_id,
name user_name,
email user_email,
password user_password
FROM
user
WHERE
id=#{user_id};
</select>
</mapper>

其流程是:
1.首先 client调用BlogMapper的findById方法
2.sql执行,作出回应,返回Blog的值(此时不直接存储User对象的值)
3.在Blog的mapper映射中 调用 select findOwnerOfBlog 方法 传入 user_id 查询 输出User

8.延迟加载

1
2
3
4
5
6
在上述案例的基础上,在全局配置文件中增加如下配置即可实现:
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
修改后会在需要User值时,才进行select findOwnerOfBlog 方法的触发

9.多对多的实现

10.分页查询

  1. limit显式实现
1
2
3
4
5
6
7
<select id="findByUserId" resultType="model.Blog">
select id,owner_id as ownerId,title,content
from blog
where owner_id = #{param1}
order by id asc
limit #{param2}, #{param3}
</select>
  1. rowBounds + pageHelper 实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
在接口中:
List<Blog> findByUserIdWithHelper(Long ownerId, RowBounds rowBounds);
在xml中:
<select id="findByUserIdWithHelper" resultType="model.Blog">
SELECT
id,
owner_id AS ownerId,
title,
content
FROM
blog
WHERE
owner_id = #{param1}
ORDER BY id ASC
</select>

最后还要导包,在全局配置中加入插件pagehelper:
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<property name="rowBoundsWithCount" value="true"/>
</plugin>
</plugins>

11.使用注解

在mapper接口内使用注解sql语句实现简单的查询

1
2
3
@Select("select * from blog_db.user")
List<Blog> findAll();
其他更多....用时再查

12.MyBatis的二级缓存机制

1
2
3
4
5
6
7
8
9
10
11
12
1.一级缓存默认开启
范围:Mapper(同一个mapper 相当于DAO)
清空:当有 update delete insert操作发生

2.二级缓存手动开启
范围:Session(同一个Session会话)
清空:
开启:
1.在全局配置文件中添加:
<setting name="cacheEnabled" value="true"/> <!--开启二级缓存-->
2.将Mapper序列化

优秀的学习资源