小言_互联网的博客

JavaWeb——MyBatis框架之连接池原理、MyBatis事务提交设置、动态SQL语法总结

619人阅读  评论(0)

目录

1 MyBatis连接池

1.1 UNPOOLED配置连接池的原理

1.2 POOLED配置连接池的原理

2 MyBatis的事务

3 MyBatis的动态SQL用法

3.1 if标签的使用

3.2 where标签的使用

3.3 foreach标签的使用


本次博文包括比较零散的MyBatis内容,包括MyBatis的连接池、事务和动态SQL语句的用法。

1 MyBatis连接池

实际开发中都会使用连接池,因为可以减少获取连接消耗的时间,连接池就是用来存储连接的一个容器,通常用一个集合对象表示,该集合必须是线程安全的,不能两个线程拿到同一个连接,该集合还必须实现队列的特性,先进先出。

MyBatis连接池的配置有3种方式,在主配置文件SqlMapConfig.xml的dataSource标签配置,其中type属性表示了采用了哪种连接池方式:

  • 1)POOLED:传统的javax.sql.DataSource规范中的连接池,MyBatis有规范的实现;
  • 2)UNPOOLED:传统的获取连接的方式,也实现了javax.sql.DataSource接口,但没有使用池的思想,每次用都是重新获取连接;
  • 3)JNDI:采用服务器提供的JNDI技术实现,来获取DataSource对象,不同服务器能拿到的DataSource不同。需要注意的是,这种方式若不是web或maven的war工程,是不能使用的。如Tomcat服务器采用的是dbcp连接池。

1.1 UNPOOLED配置连接池的原理

我们使用上一博文的工程为基础进行演示分析,首先把SqlMapConfig.xml的dataSource标签的type属性取值为POOLED,运行测试类中的testFindAll方法,观察打印输出的信息:

再把SqlMapConfig.xml的dataSource标签的type属性取值为UNPOOLED,运行测试类中的testFindAll方法,观察打印输出的信息:

以上对比,我们可以知道,在使用UNPOOLED时,是直接创建连接的,用完后就关闭了,没有池子。

实际上UNPOOLED和POOLED分别对应的类是UnpooledDataSource和PooledDataSource,我们在在IDEA中打开UnpooledDataSource类,一路跟踪方法,可以发现这个原理:

getConnection()方法->doGetConnection()方法->doGetConnection():

1.2 POOLED配置连接池的原理

打开PooledDataSource类,一路跟踪方法:getConnection()->popConnection():

我们实际开发中一般都是使用POOLED。

2 MyBatis的事务

关于事务,不做过多说明了,可以参照下之前的博文。MyBatis中的事务是通过SqlSession对象的commit方法和rollback方法实现事务的提交和回滚。在上一博文中,我们对数据库的增删改查操作发现,必须使用sqlSession.commit()方法提交事务,原因是什么呢?

那是因为从连接池取出的连接都会调用connection.setAutoCommit(false)方法关闭自动提交事务,这一点从打印的信息就可以验证:

所以,要想不进行手动提交事务,是可以设置的,在此处设置为true即可:

【注意】:设置自动提交事务,这种在实际开发中也是不常用的,因为每一次操作数据库都要提交一次事务,这会加大开销,最明显的例子就是往数据库中批量插入数据时,每次都提交一次事务的话,插入速度是很慢的。

3 MyBatis的动态SQL用法

由上一博文我们熟悉了使用MyBatis的CRUD简单操作,但是我们发现操作的输入条件都比较单一,或者是指定id查询的、或者是查询所有的、或者是根据用户名模糊查询的,那要是实际业务中涉及到查询条件比较复杂的场景该怎么办?所以,这里就用到了动态SQL。

3.1 if标签的使用

if标签在多条件组合查询中比较常用,根据实体类的不同取值,使用不同的sql语句查询,以一个具体的例子看下用法:

1)用户接口中添加 根据输入的参数条件查询 方法:


  
  1. //用户持久层接口
  2. public interface UserDao {
  3. //根据输入的参数条件查询,user就是查询的条件,可能只有其中一个属性,也可能都有或都没有
  4. List<User> findUserByCondition(User user);
  5. }

2)用户映射配置文件中配置,注意if的写法格式,其中的1个条件内的组合用 and连接(不能用&&),有多个条件就用多个if标签


  
  1. <!-- 根据条件查询-->
  2. <select id="findUserByCondition" parameterType="com.winter.domain.User" resultType="com.winter.domain.User">
  3. select *from user where 1=1
  4. <if test="username != null and username != ''">
  5. and username LIKE #{username}
  6. </if>
  7. <if test="sex != null and sex != ''">
  8. and sex = #{sex}
  9. </if>
  10. </select>

3)测试类中进行测试:查询姓名中包含“王”的女性用户


  
  1. //测试使用动态sql查询
  2. @Test
  3. public void testFindByCondition(){
  4. User user = new User();
  5. user.setUsername( "%王%");
  6. user.setSex( "女");
  7. List<User> users = userDao.findUserByCondition(user);
  8. for (User user1 : users) {
  9. System.out.println(user1);
  10. }
  11. }

3.2 where标签的使用

上述if标签 select * from user 后要加个条件whre 1=1,这个就是让其永远为真,理解起来挺另类的,所以可以使用where标签,更直观些,使用起来比较方便,就是将if内的条件用where标签包裹起来,映射配置文件中修改如下:


  
  1. <!-- 根据条件查询-->
  2. <select id="findUserByCondition" parameterType="com.winter.domain.User" resultType="com.winter.domain.User">
  3. select *from user
  4. <where>
  5. <if test="username != null and username != ''">
  6. and username LIKE #{username}
  7. </if>
  8. <if test="sex != null and sex != ''">
  9. and sex = #{sex}
  10. </if>
  11. </where>
  12. </select>

3.3 foreach标签的使用

若我们要查询多个指定id用户信息该怎么办?SQL语句是很容易写的:select * from user where id in(1,2),但是在MyBatis映射配置文件中如何传递参数呢? 这时候就用到了foreach标签,其就是来遍历集合的,属性如下:

collection 要遍历的集合元素
open 语句的开始部分
close 语句结束部分
item

遍历集合的每个元素,生产的变量,可以自定义,但要和#{}中的保持一致

sperator 分隔符

1)QueryVo类中添加ids List集合;

2)用户接口中添加 根据QueryVo的id集合查询用户 方法:


  
  1. public interface UserDao {
  2. //根据QueryVo的id集合查询用户
  3. List<User> findUserInIds(QueryVo vo);
  4. }

3)用户映射配置文件中配置,注意foreach的写法格式,注意item 属性名要和 #{}中的保持一致;


  
  1. <select id="findUserInIds" parameterType="com.winter.domain.QueryVo" resultType="com.winter.domain.User">
  2. select * from user
  3. <where>
  4. <if test="ids != null and ids.size()>0">
  5. <foreach collection="ids" open="and id in(" close=")" item="uid" separator=",">
  6. #{uid}
  7. </foreach>
  8. </if>
  9. </where>
  10. </select>

4)测试类中进行测试:查询id为1和2 的用户信息


  
  1. //测试使用QueryVo作为查询条件
  2. @Test
  3. public void testFindUserInIds(){
  4. QueryVo vo = new QueryVo();
  5. List<Integer> ids = new ArrayList<>();
  6. ids.add( 1);
  7. ids.add( 2);
  8. vo.setIds(ids);
  9. //5.执行查询
  10. List<User> users = userDao.findUserInIds(vo);
  11. for (User user1 : users) {
  12. System.out.println(user1);
  13. }
  14. }

需要源码的传送门在此

———————————————————————————————————

本文为博主原创文章,转载请注明出处!

若本文对您有帮助,轻抬您发财的小手,关注/评论/点赞/收藏,就是对我最大的支持!

祝君升职加薪,鹏程万里!


转载:https://blog.csdn.net/w464960660/article/details/108606644
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场