MyBatis

JDBC

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 导 jar包 mybatis的
// 加载驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 获取连接
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/myschoolxx?serverTimezone=GMT","root","123456");
// sql
String sql = "select * from login where lname=? and lpwd=?";
// 获取执行sql语句对象
Statement statm = conn.createStatement();
// 预处理sql
PreparedStatement prepstatm = conn.prepareStatement(sql);
prepstatm.setObject(1, zh);
prepstatm.setObject(2, pwd);

// 执行sql
ResultSet rs = prepstatm.executeQuery();

// 释放资源
rs.close();
prepstatm.close();
conn.close();

JDBC的弊端

硬编码 Java和SQL 不分离,代码不易维护

SQL参数固定

代码重复度高

底层技术

​ JDBC属于底层的技术,不支持分布式,缓存等技术,对于复杂场景的应对不好;

mybatis 解决了jdbc 的问题

1.数据库连接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库连接池可解决此问题。
解决:在SqlMapConfig.xml中配置数据连接池,使用连接池管理数据库链接。
2.Sql语句写在代码中造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。
解决:将Sql语句配置在XXXXmapper.xml文件中与java代码分离。
3.向sql语句传参数麻烦,因为sql语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应。
解决:Mybatis自动将java对象映射至sql语句,通过statement中的parameterType定义输入参数的类型。
4.对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成pojo对象
解析比较方便。
解决:Mybatis自动将sql执行结果映射至java对象,通过statement中的resultType定义输出结果的类型。

ORM模型

对象关系映射

ORM 模型是数据库的表和简单 Java 对象(Plain Ordinary Java Object,简称 POJO)的映射关系模型,主

要解决数据库数据和 POJO 对象的相互映射。

Mybatis和hibernate 区别

  1. Hibernate是全自动化ORM; Mybatis是半自动化ORM。

  2. Hibernate简化dao层,不用考虑SQL语句的编写和结果映射,重点放在业务逻辑上;
    Mybatis需要手写SQL语句以及结果映射。

  3. Hibernate是一个重量级的框架,内部生成SQL语句,反射操作太多,导致性能下降;
    Mybatis是一个轻量级的框架,需要自己写sql语句,有较少的反射操作。

  4. Hibernate 不方便做SQL优化,遇到较复杂的SQL语句需要绕过框架实现复杂,
    对多字段的结构进行部分映射困难;
    Mybatis 不仅可以做SQL优化还可以SQL与Java分离,还可以自行编写映射关系,
    复杂的SQL语句Mybatis效率更高

Mybatis优势:
可以进行更细致的SQL优化;容易掌握
Hibernate优势;
dao层开发比mybatis简单,mybatis需要维护SQL和结果映射

​ hibernate数据库移植性好

MyBatis快速开始

MyBatis定义

MyBatis是一款ORM模型支持定制化 SQL、存储过程以及高级映射。可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 首先倒 jar包	Build Path
// 配置文件
// 1.获取配置资源
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");

// 2.构建可以获取连接对象
SqlSessionFactory builder = new SqlSessionFactoryBuilder().build(inputStream);

// 3.生产SqlSession
SqlSession sqlSession = builder.openSession();

// 4.执行Sql语句(javaBean)
List<Student> slist = sqlSession.selectList("findStudent");
slist.forEach(System.out::println);

// 5.释放资源
sqlSession.close();

mybatis-config.xml (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
73
74
75
76
77
78
79
80
81
<!-- 声明 版本   编码格式 -->
<?xml version="1.0" encoding="UTF-8" ?>

<!-- 文件类型 配置 -->
<!DOCTYPE configuration

<!-- 公共的MyBatis 地址 -->
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"

<!-- .dtd 文档类型定义【声明】 -->
"http://mybatis.org/dtd/mybatis-3-config.dtd">

<!-- 标识配置文件的起始 -->
<configuration>
<!-- 配置属性的元素,可以在配置文件的上下文中使用该属性 -->
<properties resource="jdbc.properties"></properties>

<!-- 设置 -->
<settings>
<!-- 打印SQL语句 -->
<setting name="logImpl" value="STDOUT_LOGGING" />
<!--开启自动驼峰映射-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

<!-- 类型别名 -->
<typeAliases>
<!-- 给单个类起别名 -->
<!-- <typeAlias alias="Student" type="com.ape.bean.Student"/> -->

<!-- 批量起别名,扫描整个包下的类,别名为类名(大小写不敏感)一般用于xml中类型实体类 -->
<package name="com.ape.bean"/>
</typeAliases>

<!-- 配置插件 -->
<plugins>
<!-- mybatis分页插件配置 -->
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<property name="helperDialect" value="mysql"/>
<property name="reasonable" value="true"/>
</plugin>
<!--mp分页插件-->
<plugin interceptor="com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor"></plugin>
</plugins>

<!-- 和spring整合后 environments配置将废除 -->
<!-- 配置数据库环境信息,注册数据源,配置数据库事务。 -->
<!-- default 默认使用的数据库环境 -->
<environments default="development">
<!-- 单个环境信息的标识 -->
<environment id="development">
<!-- 使用jdbc事务管理 -->
<transactionManager type="JDBC" />
<!-- 数据库连接池 -->
<!-- 配置环境信息中数据源连接的信息 -->
<!-- dataSource 数据源
UNPOOLED 非连接池的数据源
POOLED 连接池的数据源
JNDI JNDI的数据源
自定义数据源 其他类型数据源
-->
<dataSource type="POOLED">
<!-- property 配置环境信息的属性 -->
<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>

<!-- 用来在MyBatis初始化的时候引入映射器 -->
<mappers>
<!-- 文件路径 -->
<!-- <mapper resource="com/ape/mapper/StudentMapper.xml"/> -->
<!-- 类路径 -->
<!-- <mapper class="com.ape.mapper.StudentMapper"/> -->
<!-- 包路径 -->
<package name="com.ape.mapper"/>
</mappers>
</configuration>

jdbc.properties

1
2
3
4
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/shopx?serverTimezone=GMT
jdbc.username=root
jdbc.password=123456

MyBatis生命周期

1)读取 MyBatis 配置文件:mybatis-config.xml 为 MyBatis 的全局配置文件,配置了MyBatis 的运行环境等信息,例如数据库连接信息。

2)加载映射文件。映射文件即 SQL 映射文件,该文件中配置了操作数据库的 SQL 语句,需要在 MyBatis 配置文件 mybatisconfig.xml 中加载。mybatis-config.xml 文件可以加载多个映射文件,每个文件对应数据库中的一张表。

3)构造会话工厂:通过 MyBatis 的环境等配置信息构建会话工厂 SqlSessionFactory。

4)创建会话对象:由会话工厂创建 SqlSession 对象,该对象中包含了执行 SQL 语句的所有方法。

5)Executor 执行器:MyBatis 底层定义了一个 Executor 接口来操作数据库,它将根据SqlSession 传递的参数动态地生成需要执行的 SQL 语句,同时负责查询缓存的维护。

6)MappedStatement 对象:在 Executor 接口的执行方法中有一个MappedStatement 类型的参数,该参数是对映射信息的封装,用于存储要映射的 SQL语句的 id、参数等信息。

7)输入参数映射:输入参数类型可以是 Map、List 等集合类型,也可以是基本数据类型和 POJO 类型。输入参数映射过程类似于 JDBC 对 preparedStatement 对象设置参数的过程。

8)输出结果映射:输出结果类型可以是 Map、 List 等集合类型,也可以是基本数据类型和 POJO 类型。输出结果映射过程类似于 JDBC 对结果集的解析过程。

image-20230507222317235

MyBatis动态代理

   1. 接口方法名要和 sqlmapper 的id名一样 能找到要执行的sql语句
2. 接口返回值的类型  要和 sqlmapper中 resultType 类型要一致(每个元素的类型)

// selectList selectOne
3. 接口中入参的类型 要和 sqlmapper 中 parameterType类型要一致
4. sqlmapper中的namescpace 的值要和 接口的类路径要一致
5. 接口要和sqlmapper 放在同一个包下
6. 接口的名字 要和 sqlmapper 文件名要一致

这六个都为了完成一个任务 映射

MyBatis 动态SQL

根据不同条件拼接 SQL 语句,实现对数据库更准确的操作
动态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
<select id="" resultType="" parameterType=""></select>    查询
resultType 简单类型映射
resultMap 复杂类型映射 和resultMap 标签中id 对应
parameterType 入参

<resultMap type="" id="">
<id></id>
<result column="" property="" javaType="" jdbcType="" />
</resultMap>
column 数据库中字段
property 类中属性
javaType Java类型
jdbcType JDBC 的类型
注:id 和 result 标签,功能类似,id 是指明数据库中主键,但Java中没有主键,所以,不用

<association property=""></association> 1对1 关系标签

<collection property="" ofType=""></collection> 1对N 关系标签
注:单表查询 可以只写映射不上的字段 属性
多表联查 每个字段都得写 不写不映射

<insert id="" parameterType="" keyProperty="" useGeneratedKeys="true"></insert> 新增
keyColumn 指明哪一列是主键,不能和 keyProperty 同时使用
keyProperty 和主键列 映射的 属性,不能和 keyColumn 同时使用
useGeneratedKeys 使用JDBC 的GeneratedKeys 方式 获取数据库内部生成的主键

<update id="" parameterType=""></update> 修改

<delete id="" parameterType=""></delete> 删除

OGNL 表达式 对象图导航语言
当传入参数是一个对象时,可以 直接使用传入参数对象的属性
<if test="OGNL表达式"></if> 判断语句

<where></where> 条件语句
1. 当有条件时,自动的添加一个 where关键词
2. 当没有条件时,不会添加where关键词
3. 会去掉where关键词后面的and/or

<choose>
<when test="OGNL表达式"></when>
<when test="OGNL表达式"></when>
<otherwise></otherwise>
</choose>
相当于switch 结构
1. 顺序(优先级)
2. 只能执行其中的一个条件
3. otherwise 可以不写

<set></set> 修改语句可用
1. 添加一个set关键词
2. 将修改的最后一个,(逗号)去掉

<trim prefix="" prefixOverrides="" suffix="" suffixOverrides=""></trim>
trim 万能标签
prefix 开头添加一个什么
prefixOverrides 开头去掉一个什么
suffix 结尾添加一个什么
suffixOverrides 结尾去掉一个什么

<foreach collection="" item="" index="" open="" close="" separator=""></foreach> 循环标签
collection 集合 可以为list 、array
item 每一个元素
index 索引
open 开始添加一个什么
close 结束添加一个什么
separator 每个元素的分隔符

<bind name="" value=""></bind> sqlMapper 文件中定义变量的

<sql id=""></sql> 定义SQL片段
将常用sql语句封装起来,可以在xml文件中随时随地的使用
<include refid=""></include> 使用SQL片段