Mybatis_连接池和级联查询
Mybatis_连接池
mybatis连接池提供了三种方式的配置
- POOLED:采用javax.sql.DataSource规范中的连接池,mybatis中有针对该规范的实现。
- UNPOOLED:采用获取连接的方式,虽然也实现了javax.sql.DataSource接口,但是没有使用连接池思想。
- JNDI:采用服务器提供的JNDI计数实现,来获取DataSource对象。不同的服务器拿到的DataSource对象是不一样的。如果不是web或者maven的war工程,不可使用此选项。(tomcat采用的连接池为dbcp连接池)
Mybatis内部分别定义了实现javax.sql.DataSource接口的UnpooledDataSource,PooledDataSource类来表示 UNPOOLED、POOLED类型的数据源。
UNPOOLED
修改配置文件SqlMapConfig.xml中dataSource的type为UNPOOLED。
<dataSource type="UNPOOLED">
<!-- 配置数据库信息 -->
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false" />
<property name="username" value="root" />
<property name="password" value="welcome1" />
</dataSource>
执行查询的结果如下:
执行查询的时候,先新建了一个连接,在执行完成之后,直接关闭了连接。
从上图中可以看出,UnpooledDataSource.java中每次都是注册驱动并获取一个新的连接,并没有连接池的概念。
POOLED
修改配置文件SqlMapConfig.xml中dataSource的type为POOLED。
<dataSource type="POOLED">
<!-- 配置数据库信息 -->
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false" />
<property name="username" value="root" />
<property name="password" value="welcome1" />
</dataSource>
执行查询的结果如下:
执行查询的时候,也是新建了一个连接,但是在执行完成之后,连接并没有直接关闭,而是将连接return回连接池中。
这里新建连接的原因是因为,程序启动之初,当连接池里面是没有可用的连接,并且现在连接池里面所有连接的数量之和小于最大连接数,就会新建一个连接并使用。具体逻辑见下图。
在PooledDataSource.java的getConnection方法中,调用了一个popConnection的方法来获取连接。
synchronized保证现场安全,防止多个线程获取到同一个连接。
自动提交
在上述的log中可以看到这一行
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3e9b1010]
从这里得知,关闭了Connection的自动提交。如果不想每次都手动提交,只需在获取SqlSession的使用使用SqlSessionFactory.openSession(true);方法即可。
动态Sql
MyBatis 提供了对 SQL 语句动态组装的功能,处理手动拼接sql的问题。
if标签
<select id="findUserByCondition" parameterType="com.xijianlv.domain.User" resultType="com.xijianlv.domain.User">
select * from user where 1=1
<if test="username != null">
and username = #{username}
</if>
</select>
- if标签的test属性必填,该属性值是一个符合OGNL要求的判断表达式,一般只用true或false作为结果。
- 判断条件property != null 或 property == null,适用于任何类型的字段,用于判断属性值是否为空。
- 判断条件property != ‘’ 或 property == ‘’,仅适用于String类型的字段,用于判断是否为空字符串。
- 当有多个判断条件时,使用and或or进行连接,嵌套的判断可以使用小括号分组,and相当于Java中的与(&&),or相关于Java中的或(||)。
测试方法
@Test
public void testFindByCondition() {
User user = new User();
user.setUsername("老王");
List<User> users = userDao.findUserByCondition(user);
for (User _user : users) {
System.out.println(_user.toString());
}
}
where标签
作用:如果该标签包含的元素中有返回值,就插入一个where,如果where后面的字符串是以AND或者OR开头的,就将它们剔除。
<select id="findUserByCondition" parameterType="com.xijianlv.domain.User" resultType="com.xijianlv.domain.User">
select * from user
<where>
<if test="username != null">
and username = #{username}
</if>
<if test="sex != null">
and sex = #{sex}
</if>
</where>
</select>
如果where中条件均不满足,sql语句中就没有了where条件。
如果有条件满足,where会自动去掉开头的and标签,保证sql正确。
foreach标签
主要用在构建 in 条件中,它可以在 SQL 语句中迭代一个集合。
<select id="findUserInIds" resultType="com.xijianlv.domain.User" parameterType="com.xijianlv.domain.QueryVo">
select * from user
<where>
<if test="ids != null and ids.size()>0">
<foreach collection="ids" open="and id in (" close=