MyBatis入门(三)

本文详细介绍了MyBatis的连接池配置,包括数据源分类、配置数据源和连接获取过程分析。此外,文章还深入讲解了MyBatis的事务控制,包括事务的提交方式和自动提交设置。最后,探讨了一对一、一对多和多对多查询的实现,提供了具体的查询策略和映射配置方法。
摘要由CSDN通过智能技术生成

0. 学习目标

  1. MyBatis连接池
  2. MyBatis的事务控制
  3. MyBatis一对一查询(一对多)
  4. MyBatis多对多查询

1. Mybatis连接池

1.1 MyBatis连接池的分类

在mybatis中,我们将他的数据源datasource分为以下几类:在这里插入图片描述
可以看出 Mybatis 将它自己的数据源分为三类:

UNPOOLED 不使用连接池的数据源

POOLED 使用连接池的数据源

JNDI 使用 JNDI 实现的数据源

具体结构如下:
在这里插入图片描述
在这里插入图片描述

在这三种数据源中,我们一般采用的是 POOLED 数据源(很多时候我们所说的数据源就是为了更好的管理数据 库连接,也就是我们所说的连接池技术)。

1.1.2 MyBatis中配置数据源


我们在配置文件中的具体配置如下:

<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>

MyBatis 在初始化时,根据的 type 属性来创建相应类型的的数据源 DataSource,即: type=”POOLED”:MyBatis 会创建 PooledDataSource 实例

type=”UNPOOLED” : MyBatis 会创建 UnpooledDataSource 实例

type=”JNDI”:MyBatis 会从 JNDI 服务上查找 DataSource 实例,然后返回使用

1.1.3 MyBatis中DataSource的存取


MyBatis 是 通 过 工 厂 模 式 来 创 建 数 据 源 DataSource 对 象 的 , MyBatis 定 义 了 抽 象 的 工 厂 接 口:org.apache.ibatis.datasource.DataSourceFactory,通过其 getDataSource()方法返回数据源 DataSource。

下面是DataSourceFactory源码,具体如下:

package org.apache.ibatis.datasource;
import java.util.Properties;
import javax.sql.DataSource;
/**
* @author Clinton Begin
*/
public interface DataSourceFactory {
   
 void setProperties(Properties props);
 DataSource getDataSource();
}

MyBatis 创建了 DataSource 实例后,会将其放到 Configuration 对象内的 Environment 对象中, 供 以后使用。 具体分析过程如下:

  1. 先进入 XMLConfigBuilder 类中,可以找到如下代码:在这里插入图片描述
  2. 分析 configuration 对象的 environment 属性,结果如下:
    在这里插入图片描述

1.1.4 MyBatis中连接获取过程分析


当我们需要创建 SqlSession 对象并需要执行 SQL 语句时,这时候 MyBatis 才会去调用 dataSource 对象 来创建java.sql.Connection对象。也就是说,java.sql.Connection对象的创建一直延迟到执行SQL语句 的时候。

@Test
public void testSql() throws Exception {
   
    InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
    SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
    SqlSession sqlSession = factory.openSession();
    List<User> list = sqlSession.selectList("findUserById",41);
    System.out.println(list.size());
}

只有当第 4 句 sqlSession.selectList(“findUserById”),才会触发 MyBatis 在底层执行下面这个方 法来创建 java.sql.Connection 对象。 如何证明它的加载过程呢? 我们可以通过断点调试,在 PooledDataSource 中找到如下 popConnection()方法,如下所示:

在这里插入图片描述分析源代码,得出 PooledDataSource 工作原理如下:
在这里插入图片描述
下面是连接获取的源代码:在这里插入图片描述最后我们可以发现,真正连接打开的时间点,只是在我们执行SQL语句时,才会进行。其实这样做我们也可以 进一步发现,数据库连接是我们最为宝贵的资源,只有在要用到的时候,才去获取并打开连接,当我们用完了就再 立即将数据库连接归还到连接池中。

2. MyBatis的事务控制

2.1.1 JDBC中事务的回顾

在 JDBC 中我们可以通过手动方式将事务的提交改为手动方式,通过 setAutoCommit()方法就可以调整。 通过 JDK 文档,我们找到该方法如下:

在这里插入图片描述

那么我们的 Mybatis 框架因为是对 JDBC 的封装,所以 Mybatis 框架的事务控制方式,本身也是用 JDBC 的 setAutoCommit()方法来设置事务提交方式的。

2.1.2 MyBatis中事务的提交方式

Mybatis 中事务的提交方式,本质上就是调用 JDBC 的 setAutoCommit()来实现事务控制。 我们运行之前所写的代码:

@Test
public void testSaveUser() throws Exception {
   
	User user = new User();
	user.setUsername("mybatis user09");
	//6.执行操作
	int res = userDao.saveUser(user);
	System.out.println(res);
	System.out.println(user.getId());
}
@Before//在测试方法执行之前执行
public void init()throws Exception {
   
	//1.读取配置文件
	in = Resources.getResourceAsStream("SqlMapConfig.xml");
	//2.创建构建者对象
	SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
	//3.创建 SqlSession 工厂对象
	factory = builder.build(in);
	//4.创建 SqlSession 对象
	session = factory.openSession();
	//5.创建 Dao 的代理对象
	userDao = session.getMapper(IUserDao.class);
}
@After//在测试方法执行完成之后执行
public void destroy() throws Exception{
   
//7.提交事务
    session.commit();
//8.释放资源
	session.close();
	in.close();
}

2.1.3MyBatis自动提交事务的设置

通过上面的研究和分析,现在我们一起思考,为什么 CUD 过程中必须使用 sqlSession.commit()提交事 务?主要原因就是在连接池中取出的连接,都会将调用 connection.setAutoCommit(false)方法,这样我们 就必须使用 sqlSession.commit()方法,相当于使用了 JDBC 中的 connection.commit()方法实现事务提交。

明白这一点后,我们现在一起尝试不进行手动提交,一样实现 CUD 操作。

@Before//在测试方法执行之前执行
public void init()throws Exception {
   
	//1.读取配置文件
	in = Resources.getResourceAsStream("SqlMapConfig.xml");
	//2.创建构建者对象
	SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
	//3.创建 SqlSession 工厂对象
	factory = builder.build(in);
	//4.创建 SqlSession 对象
	session = factory.openSession(true);
	//5.创建 Dao 的代理对象
	userDao = session.getMapper(IUserDao.class);
}
@After//在测试方法执行完成之后执行
public void destroy() throws Exception{
   
	//7.释放资源
    session.close();
	in.close()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值