该系列为imooc Java数据库开发与实战应用中MyBatis课程笔记,跟随课程加入自己见解,同时也为项目中碰到一些问题做了解答
发现问题
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--
mapper 用于定义一个映射配置文件的根节点
namespace属性是用来配置命名空间,主要进行session级别的缓存管理,命名空间默认情况下,使用我们当前操作的实体类的全路径
-->
<mapper namespace="com.damu.entity.Users">
<select id="findAll" resultType="com.damu.entity.Users">
select * from users
</select>
<select id="findById" resultType="com.damu.entity.Users">
select * from users where id =#{id}
</select>
</mapper>
执行查询时,mapper映射文件存在两个select标签,若查询的字段过多,是否意味着我们需要配置多个select标签,那怎么简化mapper文件的配置呢,可以使用动态SQL语句解决
解决问题
打开官方文档,我们可以了解到,动态SQL语句,提供一下4种
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
下面我们使用if动态SQL优化mapper映射文件中的select标签
一、优化mapper映射文件中的select标签
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--
mapper 用于定义一个映射配置文件的根节点
namespace属性是用来配置命名空间,主要进行session级别的缓存管理,命名空间默认情况下,使用我们当前操作的实体类的全路径
-->
<mapper namespace="com.damu.entity.Users">
<select id="findAll" resultType="com.damu.entity.Users">
select * from users
<if test="id !=null">
where id =#{id}
</if>
</select>
<!-- <select id="findById" resultType="com.damu.entity.Users">-->
<!-- select * from users where id =#{id}-->
<!-- </select>-->
</mapper>
二、修改UsersDAO
package com.damu.dao;
import com.damu.entity.Users;
import com.damu.utils.SqlSessionFactoryUtils;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
/**
* Created by mouwe on 2017/5/23.
*/
public class UsersDAO {
private SqlSession sqlSession;
private List<Users> list;
private Users user;
private SqlSession getSqlSession(){
sqlSession=SqlSessionFactoryUtils.getSqlSessionFactory().openSession();
return sqlSession;
}
/**
* 查询全部用户
* @return
*/
public List<Users> findAll() {
try {
list = getSqlSession().selectList("findAll");
} catch (Exception e) {
e.printStackTrace();
} finally {
sqlSession.close();
}
return list;
}
/**
* 根据编号查询单个用户
* @return
*/
public Users findById(Integer id) {
try {
user=getSqlSession().selectOne("findAll",id);//使用findAll,并传入id
} catch (Exception e) {
e.printStackTrace();
} finally {
sqlSession.close();
}
return user;
}
}
启动项目,出现了新的问题,查询不到数据
控制台报错
之所以报错,是因为User中的id属性是Integer
我们配置的mapper映射文件中select标签如下,需要传入id(Integer类型)
<select id="findUsers" resultType="com.damu.entity.Users">
select * from users
<if test="id !=null">
where id =#{id}
</if>
</select>
故我们在UsersDAO中findById方法传入的是Integer,
所有MyBatis会去Integer这个类中寻找id的getter方法,所以会报错
(个人理解,mapper中的select标签需要id,我们在UsersDAO中findById方法传入的是什么类,就从什么类里面去寻找id的getter方法,但是integer中没有id的getter方法,故报错)
三、改造代码解决id没有getter方法的问题
- 修改Users,增加两个构造方法
public Users() {
}
public Users(Integer id) {
this.id = id;
}
- 修改UsersDAO,在findById方法中,通过传入的integer id生成Users对象,把id包装在Users对象中,交给Mybatis处理,Users中有id的getter方法
package com.damu.dao;
import com.damu.entity.Users;
import com.damu.utils.SqlSessionFactoryUtils;
import org.apache.ibatis.session.SqlSession;
import java.util.List;
/**
* Created by mouwe on 2017/5/23.
*/
public class UsersDAO {
private SqlSession sqlSession;
private List<Users> list;
private Users user;
private SqlSession getSqlSession(){
sqlSession=SqlSessionFactoryUtils.getSqlSessionFactory().openSession();
return sqlSession;
}
/**
* 查询全部用户
* @return
*/
public List<Users> findAll() {
try {
list = getSqlSession().selectList("findUsers");
} catch (Exception e) {
e.printStackTrace();
} finally {
sqlSession.close();
}
return list;
}
/**
* 根据编号查询单个用户
* @return
*/
public Users findById(Integer id) {
try {
user=getSqlSession().selectOne("findUsers",new Users(id));//传入Users对象,通过id生成,把id包装在Users对象中,交给Mybatis处理,Users中有id的getter方法
} catch (Exception e) {
e.printStackTrace();
} finally {
sqlSession.close();
}
return user;
}
}
启动项目,可正常运行,实现了使用if动态SQL优化mapper映射文件中的select标签