Mybatis学习3-连接池、事务及动态SQL

连接池

1、连接池:
在实际开发中都会使用连接池。因为它可以减少我们获取连接所消耗的时间。

连接池就是用于存储连接的一个容器,这个容器其实就是一个集合对象。但是该集合必须是线程安全的,不能两个线程拿到同一个连接,而且满足队列特性,先进先出。

2、mybatis中的连接池:
mybatis连接池提供了3种配置方式:
配置的位置:
主配置文件SqlMapConfig.xml中的dataSource标签,type属性就是表示采用何种连接池方式。
type属性的值:

  • POOLED:采用传统的javax.sql.DataSource规范中的连接池,mybatis中有针对规范的实现;

    • 其实是分为空闲池和活动池,首先到空闲池查看,如果空闲池有连接,直接拿出用即可,如果空闲池没有连接了,则去活动池寻找,查看活动池中是否到了最大连接数量,如果活动池也达到了最大连接数量,则判断活动池中哪个连接是最先进来的,则经过系列操作返回这个oldest的连接。
  • UNPOOLED:采用传统的获取连接的方式,虽然也实现javax.sql.DataSource接口,但是并没有使用池的思想;

  • JNDI:采用服务器提供的JNDI技术实现,来获取DataSource对象,不同的服务器所能拿到DataSource是不一样的;

    • 注意:如果不是web或者maven的war工程,是不能使用的。学习时使用的时tomcat服务器,采用的连接池就是dbcp连接池。

MyBatis中的事务

什么是事务
  事务的四大特性ACID
  不考虑隔离性会产生的3个问题
  解决办法:四种隔离级别

它是通过sqlsession对象的commit方法和rollback方法实现事务的提交和回滚

动态SQL

主要是基于XMl配置的动态SQL语句使用,即mappers配置文件中的几个标签。

if标签的使用

1.接口中定义

1
List<User> findByCondition(User user);

2.mapper中定义

1
2
3
4
5
6
7
8
9
<select id="findByCondition" resultMap="userMap" parameterType="user">
select * from user where 1=1
<if test="userName != null">
and username = #{userName}
</if>
<if test="userSex != null">
and sex = #{userSex}
</if>
</select>

其中: 这条语句中,userName指的是实体类中的属性名, and username = #{userName}这里是将实体类的userName传给数据库的username

3.测试类中测试

1
2
3
4
5
6
7
8
9
10
11
12
@Test
public void testFindByCondition() {
// 5.执行根据条件查询
User u = new User();
u.setUserName("老王");
u.setUserSex("男");

List<User> users = userDao.findUserByCondition(u);
for (User user : users) {
System.out.println(user);
}
}

where标签的使用

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

1
2
3
4
5
6
7
8
9
10
11
12
13
<!--根据传入参数条件查询-->
<select id="findUserByCondition" resultMap="userMap" parameterType="user">
-- select * from user where 1=1
select * from user
<where>
<if test="userName != null">
and username = #{userName}
</if>
<if test="userSex != null">
and sex = #{userSex}
</if>
</where>
</select>

foreach标签的使用

用于集合中查询的SQL:select * from user where id in(41,42,45)
通过一个类中传入集合的方法
QueryVo类

1
2
3
4
5
6
7
@Getter
@Setter
public class QueryVo {

private User user;
private List<Integer> ids;
}

1.接口中定义

1
2
3
4
5
6
/**
* 根据Queryvo中提供的id集合,查询用户信息
* @param vo
* @return
*/
List<User> findUserInIds(QueryVo vo);

2.mapper中定义

1
2
3
4
5
6
7
8
9
10
11
<!--根据queryvo中Id集合实现查询用户列表-->
<select id="findUserInIds" resultMap="userMap" parameterType="queryvo">
select * from user
<where>
<if test="ids != null and ids.size()>0">
<foreach collection="ids" open="and id in (" close=")" item="uuuuid" separator=",">
#{uuuuid}
</foreach>
</if>
</where>
</select>

注意if标签中的内容都是来源于ParameterType参数。

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

​ collection:代表要遍历的集合元素,注意编写时不要写#{}

​ open:代表语句的开始部分

​ close:代表结束部分

​ item:代表遍历集合的每个元素,生成的变量名

​ separator:代表分隔符

3.测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Test
public void testFindUserInIds() {
// 5.执行根据QueryVo中的Id集合进行查询
QueryVo vo = new QueryVo();
List<Integer> list = new ArrayList<Integer>();
list.add(41);
list.add(42);
list.add(43);
vo.setIds(list);
List<User> users = userDao.findUserInIds(vo);
for (User user : users) {
System.out.println(user);
}
}

抽取重复的SQL

1.定义

1
2
3
4
<!--抽取重复的sql语句-->
<sql id="defaultUser">
select * from user
</sql>

2.使用

1
2
3
4
5
6
7
8
9
 <!--抽取重复的sql语句-->
<sql id="defaultUser">
select * from user
</sql>

<!--配置查询所有 其中id不能乱写必须是dao接口中的方法 resultType写的是实体类的全路径-->
<select id="findAll" resultMap="userMap">
<include refid="defaultUser"/>
</select>

注意: 尽量不要使用分号,SQL语句可能会拼接

:转载文章请注明出处,谢谢~