本次博文包括比较零散的MyBatis内容,包括MyBatis的连接池、事务和动态SQL语句的用法。
实际开发中都会使用连接池,因为可以减少获取连接消耗的时间,连接池就是用来存储连接的一个容器,通常用一个集合对象表示,该集合必须是线程安全的,不能两个线程拿到同一个连接,该集合还必须实现队列的特性,先进先出。
MyBatis连接池的配置有3种方式,在主配置文件SqlMapConfig.xml的dataSource标签配置,其中type属性表示了采用了哪种连接池方式:
我们使用上一博文的工程为基础进行演示分析,首先把SqlMapConfig.xml的dataSource标签的type属性取值为POOLED,运行测试类中的testFindAll方法,观察打印输出的信息:
再把SqlMapConfig.xml的dataSource标签的type属性取值为UNPOOLED,运行测试类中的testFindAll方法,观察打印输出的信息:
以上对比,我们可以知道,在使用UNPOOLED时,是直接创建连接的,用完后就关闭了,没有池子。
实际上UNPOOLED和POOLED分别对应的类是UnpooledDataSource和PooledDataSource,我们在在IDEA中打开UnpooledDataSource类,一路跟踪方法,可以发现这个原理:
getConnection()方法->doGetConnection()方法->doGetConnection():
打开PooledDataSource类,一路跟踪方法:getConnection()->popConnection():
我们实际开发中一般都是使用POOLED。
关于事务,不做过多说明了,可以参照下之前的博文。MyBatis中的事务是通过SqlSession对象的commit方法和rollback方法实现事务的提交和回滚。在上一博文中,我们对数据库的增删改查操作发现,必须使用sqlSession.commit()方法提交事务,原因是什么呢?
那是因为从连接池取出的连接都会调用connection.setAutoCommit(false)方法关闭自动提交事务,这一点从打印的信息就可以验证:
所以,要想不进行手动提交事务,是可以设置的,在此处设置为true即可:
【注意】:设置自动提交事务,这种在实际开发中也是不常用的,因为每一次操作数据库都要提交一次事务,这会加大开销,最明显的例子就是往数据库中批量插入数据时,每次都提交一次事务的话,插入速度是很慢的。
由上一博文我们熟悉了使用MyBatis的CRUD简单操作,但是我们发现操作的输入条件都比较单一,或者是指定id查询的、或者是查询所有的、或者是根据用户名模糊查询的,那要是实际业务中涉及到查询条件比较复杂的场景该怎么办?所以,这里就用到了动态SQL。
if标签在多条件组合查询中比较常用,根据实体类的不同取值,使用不同的sql语句查询,以一个具体的例子看下用法:
1)用户接口中添加 根据输入的参数条件查询 方法:
//用户持久层接口
public interface UserDao {
//根据输入的参数条件查询,user就是查询的条件,可能只有其中一个属性,也可能都有或都没有
List<User> findUserByCondition(User user);
}
2)用户映射配置文件中配置,注意if的写法格式,其中的1个条件内的组合用 and连接(不能用&&),有多个条件就用多个if标签
<!-- 根据条件查询-->
<select id="findUserByCondition" parameterType="com.winter.domain.User" resultType="com.winter.domain.User">
select *from user where 1=1
<if test="username != null and username != ''">
and username LIKE #{username}
</if>
<if test="sex != null and sex != ''">
and sex = #{sex}
</if>
</select>
3)测试类中进行测试:查询姓名中包含“王”的女性用户
//测试使用动态sql查询
@Test
public void testFindByCondition(){
User user = new User();
user.setUsername("%王%");
user.setSex("女");
List<User> users = userDao.findUserByCondition(user);
for (User user1 : users) {
System.out.println(user1);
}
}
上述if标签 select * from user 后要加个条件whre 1=1,这个就是让其永远为真,理解起来挺另类的,所以可以使用where标签,更直观些,使用起来比较方便,就是将if内的条件用where标签包裹起来,映射配置文件中修改如下:
<!-- 根据条件查询-->
<select id="findUserByCondition" parameterType="com.winter.domain.User" resultType="com.winter.domain.User">
select *from user
<where>
<if test="username != null and username != ''">
and username LIKE #{username}
</if>
<if test="sex != null and sex != ''">
and sex = #{sex}
</if>
</where>
</select>
若我们要查询多个指定id用户信息该怎么办?SQL语句是很容易写的:select * from user where id in(1,2),但是在MyBatis映射配置文件中如何传递参数呢? 这时候就用到了foreach标签,其就是来遍历集合的,属性如下:
collection | 要遍历的集合元素 |
---|---|
open | 语句的开始部分 |
close | 语句结束部分 |
item | 遍历集合的每个元素,生产的变量,可以自定义,但要和#{}中的保持一致 |
sperator | 分隔符 |
1)QueryVo类中添加ids List集合;
2)用户接口中添加 根据QueryVo的id集合查询用户 方法:
public interface UserDao {
//根据QueryVo的id集合查询用户
List<User> findUserInIds(QueryVo vo);
}
3)用户映射配置文件中配置,注意foreach的写法格式,注意item 属性名要和 #{}中的保持一致;
<select id="findUserInIds" parameterType="com.winter.domain.QueryVo" resultType="com.winter.domain.User">
select * from user
<where>
<if test="ids != null and ids.size()>0">
<foreach collection="ids" open="and id in(" close=")" item="uid" separator=",">
#{uid}
</foreach>
</if>
</where>
</select>
4)测试类中进行测试:查询id为1和2 的用户信息
//测试使用QueryVo作为查询条件
@Test
public void testFindUserInIds(){
QueryVo vo = new QueryVo();
List<Integer> ids = new ArrayList<>();
ids.add(1);
ids.add(2);
vo.setIds(ids);
//5.执行查询
List<User> users = userDao.findUserInIds(vo);
for (User user1 : users) {
System.out.println(user1);
}
}
———————————————————————————————————
本文为博主原创文章,转载请注明出处!