MyBatis连接池的深入和动态SQL详解

网友投稿 255 2022-08-29


MyBatis连接池的深入和动态SQL详解

目录一,Mybatis 连接池与事务深入1.1 Mybatis 的连接池技术1.1.1 Mybatis 连接池的分类1.1.2 Mybatis 中数据源的配置1.2 Mybatis 的事务控制1.2.1 JDBC 中事务的回顾1.2.2 Mybatis 中事务提交方式1.2.3 Mybatis 自动提交事务的设置二.Mybatis 的动态 SQL 语句2.1 动态 SQL 之标签2.1.1 持久层 Dao 接口2.1.2 持久层 Dao 映射配置2.1.3 测试2.2 动态 SQL 之标签2.2.1 持久层 Dao 映射配置2.3 动态标签之标签2.3.1 在 QueryVo 中加入一个 List 集合用于封装参数2.3.2 持久层 Dao 接口2.3.3 持久层 Dao 映射配置2.3.4 编写测试方法2.4 Mybatis 中简化编写的 SQL 片段2.4.2 引用代码片段

一,Mybatis 连接池与事务深入

1.1 Mybatis 的连接池技术

Mybatis 中连接池技术,它采用的是自己的连接池技术。在 Mybatis 的 SqlMapConfig.xml 配置文件中,通过来实现 Mybatis 中连接池的配置。

1.1.1 Mybatis 连接池的分类

在 Mybatis 中我们将它的数据源 dataSource 分为以下几类:

可以看出 Mybatis 将它自己的数据源分为三类:

UNPOOLED 不使用连接池的数据源 POOLED 使用连接池的数据源 JNDI 使用 JNDI 实现的数据源

具体结构如下:

相应地,MyBatis 内部分别定义了实现了 java.sql.DataSource 接口的 UnpooledDataSource,PooledDataSource 类来表示 UNPOOLED、POOLED 类型的数据源。

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

1.1.2 Mybatis 中数据源的配置

MyBatis 在初始化时,根据的 type 属性来创建相应类型的的数据源 DataSource,即:

type=”POOLED”:MyBatis 会创建 PooledDataSource 实例type=”UNPOOLED” : MyBatis 会创建 UnpooledDataSource 实例type=”JNDI”:MyBatis 会从 JNDI 服务上查找 DataSource 实例,然后返回使用

我们的数据源配置就是在 SqlMapConfig.xml 文件中,具体配置如下:

1.2 Mybatis 的事务控制

1.2.1 JDBC 中事务的回顾

在 JDBC 中我们可以通过手动方式将事务的提交改为手动方式,通过 setAutoCommit()方法就可以调整。

通过 JDK 文档,我们找到该方法如下:

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

1.2.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 = http://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();

}

默认 setAutoCommit()方法,在执行时它的值被设置为 false 了,所以我们在 CUD 操作中,必须通过 sqlSession.commit()方法来执行提交操作。

1.2.3 Mybatis 自动提交事务的设置

通过上面的研究和分析,现在我们一起思考,为什么 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();

}

事务就设置为自动提交了,同样可以实现CUD操作时记录的保存。虽然这也是一种方式,但就编程而言,设置为自动提交方式为 false 再根据情况决定是否进行提交,这种方式更常用。因为我们可以根据业务情况来决定提交是否进行提交。

二.Mybatis 的动态 SQL 语句

Mybatis 的映射文件中,前面我们的 SQL 都是比较简单的,有些时候业务逻辑复杂时,我们的 SQL 是动态变化的,此时在前面的学习中我们的 SQL 就不能满足要求了。

参考的官方文档,描述如下:

2.1 动态 SQL 之标签

我们根据实体类的不同取值,使用不同的 SQL 语句来进行查询。比如在 id 如果不为空时可以根据 id 查询,如果 username 不同空时还要加入用户名作为条件。这种情况在我们的多条件组合查询中经常会碰到。

2.1.1 持久层 Dao 接口

/**

* 根据用户信息,查询用户列表

* @param user

* @return

*/

List findByUser(User user);

2.1.2 持久层 Dao 映射配置

select * from user where 1=1

and username like #{username}

and address like #{address}

注意:标签的 test 属性中写的是对象的属性名,如果是包装类的对象要使用 OGNL 表达式的写法。

另外要注意 where 1=1 的作用~!

2.1.3 测试

@Test

public void testFindByUser() {

User u = new User();

u.setUsername("%王%");

u.setAddress("%顺义%");

//6.执行操作

List users = userDao.findByUser(u);

for(User user : users) {

System.out.println(user);

} }

2.2 动态 SQL 之标签

为了简化上面 where 1=1 的条件拼装,我们可以采用标签来简化开发。

2.2.1 持久层 Dao 映射配置

and username like #{username}

and address like #{address}

2.3 动态标签之标签

需求

传入多个 id 查询用户信息,用下边两个 sql 实现:

SELECT * FROM USERS WHERE username LIKE ‘%张%' AND (id =10 OR id =89 OR id=16)

SELECT * FROM USERS WHERE username LIKE ‘%张%' AND id IN (10,89,16)

这样我们在进行范围查询时,就要将一个集合中的值,作为参数动态添加进来。

这样我们将如何进行参数的传递?

2.3.1 在 QueryVo 中加入一个 List 集合用于封装参数

/**

*

*

Title: QueryVo

*

Description: 查询的条件

*

Company: http://itheima.com/

*/

public class QueryVo implements Serializable {

private List ids;

public List getIds() {

return ids; }

public void setIds(List ids) {

this.ids = ids; } }

2.3.2 持久层 Dao 接口

/**

* 根据 id 集合查询用户

* @param vo

* @return

*/

List findInIds(QueryVo vo);

2.3.3 持久层 Dao 映射配置

separator=",">

#{uid}

separator=",">

#{uid}

SQL 语句:

select 字段 from user where id in (?)

标签用于遍历集合,它的属性:

collection:代表要遍历的集合元素,注意编写时不要写#{}open:代表语句的开始部分close:代表结束部分item:代表遍历集合的每个元素,生成的变量名sperator:代表分隔符

2.3.4 编写测试方法

@Test

public void testFindInIds() {

QueryVo vo = new QueryVo();

List ids = new ArrayList();

ids.add(41);

ids.add(42);

ids.add(43);

ids.add(46);

ids.add(57);

vo.setIds(ids);

//6.执行操作

List users = userDao.findInIds(vo);

for(User user : users) {

System.out.println(user);

} }

2.4 Mybatis 中简化编写的 SQL 片段

Sql 中可将重复的 sql 提取出来,使用时用 include 引用即可,最终达到 sql 重用的目的。

2.4.1 定义代码片段

select * from user

2.4.2 引用代码片段

where id = #{uid}


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Python测试用例生成脚本(合并相应单元格以及写入单行数据)代码实例
下一篇:IornPython的IDE安装步骤(IornPython其他版本只需下载相应版本即可)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~