MyBatis 框架概述

​ mybatis是一个优秀的基于 java 的持久层框架,它内部封装了 jdbc,使开发者只需要关注 sql语句本身, 而不需要花费精力去处理加载驱动创建连接创建 statement 等繁杂的过程。

​ mybatis通过xml 或注解的方式将要执行的各种statement配置起来,并通过java对象和statement 中 sql 的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射为 java 对象并 返回。

​ 采用 ORM (Object Relational Mapping 对象关系映射,就是把数据库表和实体类以及实体类的属性对应起来)思想解决了实体和数据库映射的问题,对 jdbc进行了封装,屏蔽了 jdbc api 底层访问细节,使我 们不用与 jdbc api 打交道,就可以完成对数据库的持久化操作。

Jdbc 问题分析

1、数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。

2、Sql 语句在代码中硬编码,造成代码不易维护,实际应用 sql 变化的可能较大,sql 变动需要改变 java 代码。

3、使用 preparedStatement 向占有位符号传参数存在硬编码,因为 sql 语句的 where 条件不一定,可能 多也可能少,修改 sql 还要修改代码,系统不易维护。

4、对结果集解析存在硬编码(查询列名),sql 变化导致解析代码变化,系统不易维护,如果能将数据库记 录封装成 pojo 对象解析比较方便。

入门案例

需要依赖:mysql mybatis junit log4j

环境搭建

  1. 创建maven工程导入坐标

  2. 创建实体类和dao接口

  3. 创建mybatis的主配置文件

  4. 创建映射配置文件

注意事件

  1. 创建IUserDao.xml和IUserDao.java是为了和我们之前的知识保持一致

在mybatis中把持久层的操作接口名称和映射文件也叫作Mapper

所以,IUserDao 和IUserMapper 一样

  1. 在idea中创建目录中 和包不一样 com.xyt.dao 它是三级结构

目录在创建时.com.xyt.dao 是一级目录(这个要特别小心,曾经在这里找了很久的bug一直读取不到对应的dao.xml)

  1. mybatis的映射配置文件位置必须和dao接口的包结构相同
  2. 映射配置文件的mapper标签namespace属性的取值必须是dao接口的全限定类名
  3. 映射配置文件的操作配置,id属性的取值必须是dao接口的方法名

当我们遵从345点,开发中就无须再写dao实现类

注意事项:

不要忘记在映射配置中告知mybatis要封装对哪个实体类中

配置的方式:指定实体类的全限定类名

resources/SqlMapConfig.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
<?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="mysql">
<!--配置mysql的环境-->
<environment id="mysql">
<!--配置事务的类型-->
<transactionManager type="JDBC"></transactionManager>
<!--配置数据源(连接池)-->
<dataSource type="POOLED">
<!--配置连接数据库4个的基本信息-->
<property name="driver" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/eesy"></property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</dataSource>
</environment>
</environments>

<!--指定配置文件的位置,映射配置文件指的是每个Dao独立的配置文件-->
<mappers>
<mapper resource="com/xyt.dao/IUserDao.xml"/>
</mappers>
</configuration>

Mapper: resources/com.xyt.dao.IUserDao.xml

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">
<mapper namespace="com.xyt.dao.IUserDao">
<!--配置查询所有-->
<select id="findAll" resultType="com.xyt.domain.User">
select * from user
</select>
</mapper>

测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public static void main(String[] args) throws Exception{
//步骤:
//1.读取配置文件
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建一个sqlsessionfactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
//3.使用工厂生产Sqlsession对象
SqlSession session = factory.openSession();
//4.使用sqlsession创建dao接口的代理对象
IUserDao userDao = session.getMapper(IUserDao.class);
//5.使用代理对象执行方法
List<User> users = userDao.findAll();
for (User user: users) {
System.out.println(user);

}
//6.释放资源
session.close();
in.close();

入门案例基于注解改造

删除IUserDao.xml,在dao接口的方法上使用@Select注解,并且制定SQL语句,同时需要在SqlMapConfig中的Mapper配置时,使用class属性 制定dao接口的全限定类名

明确:我们在实际开发中都是越简便越好,所以都是采用不写dao实现类的方式,不管是用xml还是注解 (现在有许多代码生成器 一般还是使用xml)

SqlMapConfig.xml

1
2
3
4
5
6
    <!--指定配置文件的位置,映射配置文件指的是每个Dao独立的配置文件
如果用注解配置 此处应使用class属性磁钉被注解的dao全限定类名-->
<mappers>
<mapper class="com.xyt.dao.IUserDao"/>
</mappers>
</configuration>

IUserDao接口

1
2
3
4
5
6
7
8
9
public interface IUserDao {
/**
* 查询所有操作
* @return
*/
@Select("select * from user")
List<User> findAll();

}

入门案例基于实现类改造

测试方法

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
/**
*
* @author Xyingtao
* @date 2020/4/23
*/
public class MybatisTest {
/**
* 入门案例
* @param args
*/
public static void main(String[] args) throws Exception{
//1.读取配置文件
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建一个sqlsessionfactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
//3.使用工厂生产Sqlsession对象
IUserDao userDao = new UserDaoImpl(factory);
//4.使用工厂创建dao对象

//4.使用代理对象执行方法
List<User> users = userDao.findAll();
for (User user: users) {
System.out.println(user);

}
//6.释放资源
in.close();
}
}

实现类

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
package com.xyt.dao.impl;

import com.xyt.dao.IUserDao;
import com.xyt.domain.User;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import java.util.List;
/**
*
* @author Xyingtao
* @date 2020/4/26
*/
public class UserDaoImpl implements IUserDao {


private SqlSessionFactory factory;
public UserDaoImpl(SqlSessionFactory factory) {
this.factory = factory;
}

public List<User> findAll() {
//使用工厂创建sqlsession对象
SqlSession session = factory.openSession();
//使用session执行查询所有方法
List<User> users = session.selectList("com.xyt.dao.IUserDao.findAll");
session.close();
//3.返回查询结果
return users;
}
}

设计模式分析

1.读取配置文件

​ InputStream in = Resources.getResourceAsStream(“SqlMapConfig.xml”);

(绝对路径:d:/xxx/xxx/xml

相对路径:src/java/main/xxx.xml 一般开发都不用)

第一个: 使用类加载器.他只能读取类路径的配置文件

第二个: 使用ServletContext对象的getRealPath()

2.创建一个sqlsessionfactory工厂

创建工厂mybatis使用了构建者模式 优势:把对象的创建细节隐藏,是使用者直接调用方法即可拿到对象

​ SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
​ SqlSessionFactory factory = builder.build(in);

in

builder就是构建者 ,把繁琐的细节封装

3.使用工厂生产Sqlsession对象

使用了工厂模式 优势: 解耦 (降低类之间的依赖关系)

SqlSession session = factory.openSession();

4.使用sqlsession创建dao接口的代理对象

代理模式 创建dao接口实现类使用了代理模式 优势:不修改源码的基础上对已有方法增强

​ IUserDao userDao = session.getMapper(IUserDao.class);

5.使用代理对象执行方法

​ List users = userDao.findAll();
​ for (User user: users) {
​ System.out.println(user);

}

6.释放资源

​ session.close();
​ in.close();

涉及到的设计模式,以后看情况边学习边总结成新的帖子吧

资料参考: 黑马程序员