Mybatis学习笔记:
Mybatis中的连接池
连接池就是用于存储连接的一个容器,一个集合对象,该集合必须是线程安全的,不能两个线程拿到同一链接。该集合还必须实现队列的特性:先进先出
Mybatis连接池提供了3种方式的配置:
- 配置的位置:
主配置文件SqlMapConfig.xml中的dataSource标签,type属性就是表示采用何种连接方式。 - Type属性的取值:
POOLED采用传统的javax.sql.DataSource规范中的连接池,mybatis中有针对规范的实现。
UNPOOLED采用传统的获取连接的方式,虽然也实现Javax.sql.DataSource接口,但是并没有使用池的思想。
JNDI 采用服务器提供的技术实现提供的JNDI技术实现,来获取DataSource对象,不同的服务器所能拿到的DataSource是不一样的,注意:如果不是web或者maven的war工程,是不能使用的。
<dataSource type="POOLED">
<property name="driver" value="${driver}"></property>
<property name="url" value="${url}"></property>
<property name="username" value="${username}"></property>
<property name="password" value="${password}"></property>
</dataSource>
动态SQL语句
动态 SQL 是 MyBatis 的强大特性之一。使用动态 SQL可以让我们在拼接 SQL 语句时更加容易。
if 标签:
可以根据根据传入的实体类,判断哪些属性不为空,并以此作为查询条件。
where标签:
当我们使用多个if标签进行拼接时,由于我们不知道有多少个要拼接的语句所以我们一般采用的拼接形式为:select * from user where 1=1 and ... and...
,由where 1=1 这一个恒成立的式子来使后面的拼接语句都变成and...
形式,Mybatis同时也提供了有相同功能的标签。
例:
<!--根据条件查询用户 -->
<select id="findUserByCondition" resultType="com.ly.domain.User">
select * from user
<!--(where 1 = 1)与(<where></where>)等价-->
<where>
<if test="username != null">
and username = #{username}
</if>
<if test="sex != null">
and sex = #{sex}
</if>
</where>
</select>
foreach 标签:
foreach 标签主要用于构建 in 条件,可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象传递给 foreach 作为集合参数。也常用到批量删除、添加等操作中。
<foreach></foreach> 标签用于遍历集合,每个属性的作用如下所示:
- collection :
代表要遍历的集合或数组,这个属性是必须的。如果是遍历数组,那么该值只能为 array。
- open :
代表语句的开始部份。
- close :
代表语句的结束部份。
- item :
代表遍历集合时的每个元素,相当于一个临时变量。
- separator :
代表拼接每个元素之间的分隔符。
当使用可迭代对象或者数组时,index 是当前迭代的次数,item 的值是本次迭代获取的元素
。当使用 **Map 对象(或者 Map.Entry 对象的集合)**时,index 是键,item 是值。
例:
首先修改 QueryVo 类,增加一个成员变量用于存放 id 集合,并增加其 getter()/setter()
public class QueryVo {
private User user;
private List<Integer> ids;
public User getUser() {return user;}
public void setUser(User user) {this.user = user;}
public List<Integer> getIds() {return ids;}
public void setIds(List<Integer> ids) {this.ids = ids;}
}
使用foreach
<!--根据Queryvo中的集合实现查询用户列表-->
<select id="findUserInIds" parameterType="com.ly.domain.QueryVo" resultType="com.ly.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>
定义 SQL 片段:
在上面的例子中,我们在每条 SQL 中都用到了 select * from user ,因此,我们可以把该语句定义为 SQL 片段,以供复用,减少工作量。
使用方法:
<sql id="defaultUser">
select * from user
</sql>
<!-- 配置查询所有-->
<select id="findAll" resultType="com.ly.domain.User">
<include refid="defaultUser"></include>
<!--select * from user-->
</select>
测试代码
配置持久层接口IUserDao:
/**
* @Author: Ly
* @Date: 2020-07-12 11:29
*/
public interface IUserDao {
/**
* 根据传入参数条件
* @param user 查询的条件,有可能是任何几个属性,也可能都有,或都没有
* @return
*/
List<User> findUserByCondition(User user);
/**
* 根据queryuo中提供的id集合,查询用户信息
* @param vo
* @return
*/
List<User> findUserInIds(QueryVo vo);
}
配置接口映射文件IUserDao.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ly.dao.IUserDao">
<sql id="defaultUser">
select * from user
</sql>
<!--根据条件查询用户 -->
<select id="findUserByCondition" resultType="com.ly.domain.User">
<include refid="defaultUser"></include>
select * from user
<!--(where 1 = 1)与(<where></where>)等价-->
<where>
<if test="username != null">
and username = #{username}
</if>
<if test="sex != null">
and sex = #{sex}
</if>
</where>
</select>
<!--根据Queryvo中的集合实现查询用户列表-->
<select id="findUserInIds" parameterType="com.ly.domain.QueryVo" resultType="com.ly.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>
</mapper>
创建MybatisTest类测试方法:
public class MybatisTest {
private InputStream in;
private SqlSession sqlSession;
private IUserDao userDao;
@Before//再测试方法执行之前执行
public void init() throws Exception{
//1.读取配置文件,生成字节输入流
in= Resources.getResourceAsStream("SqlMapConfig.xml");
//2.创建SqlSessionFactory工厂,获取SqlSessionFactory对象
SqlSessionFactory factory=new SqlSessionFactoryBuilder().build(in);
//3.使用工厂生产SqlSession对象
sqlSession=factory.openSession();
//4.使用SqlSession创建Dao接口的代理对象
userDao=sqlSession.getMapper(IUserDao.class);
}
@After//用于在测试方法执行之后执行
public void destroy() throws Exception{
//提交事务
sqlSession.commit();
//6.释放资源
sqlSession.close();
in.close();
}
/**
* 测试查询所有
*/
@Test
public void testFindByCondition(){
User u = new User();
u.setUsername("张三");
//5.使用代理对象执行方法
List<User> users=userDao.findUserByCondition(u);
for (User user :users){
System.out.println(user);
}
}
/**
* 测试foreach查询
*/
@Test
public void testFindInIds(){
QueryVo vo =new QueryVo();
List<Integer> list =new ArrayList<Integer>();
list.add(2);
list.add(3);
list.add(4);
vo.setIds(list);
//5.使用代理对象执行方法
List<User> users=userDao.findUserInIds(vo);
for (User user :users){
System.out.println(user);
}
}
}