Mybatis学习(五)
7.MyBatis映射文件
7.1 输入映射
在mybatis中,输入映射使用parameterType来进行映射。
7.1.1 映射简单类型
参考 根据用户id 查询用户信息 parameterType="int"
7.1.2 映射pojo
参考 添加用户信息 parameterType="com.jxdd.mybatis.po.User"
7.1.3 映射包装pojo
开发中通过pojo传递查询条件 ,查询条件是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数。
7.1.3.1 需求
综合查询用户信息,需要传入查询条件复杂,比如(用户信息、订单信息、商品信息).
7.1.3.2 创建包装pojo类
一般User.java类要和数据表表字段一致,最好不要在这里面添加其他字段,当使用mybatis的逆向工程时,会根据表结构,生成po类,如果在po类中扩展字段,此时会被覆盖掉。
所以针对要扩展的po类,我们需要创建一个扩展类,来继承它。
1 public class UserExt extends User{ 2 //这里可以定义User的一些扩展信息 3 }
定义POJO包装类
1 public class UserQueryVO { 2 private UserExt userExt; 3 4 public UserExt getUserExt() { 5 return userExt; 6 } 7 8 public void setUserExt(UserExt userExt) { 9 this.userExt = userExt; 10 } 11 }
7.1.3.3 编写mapper接口
1 public List<UserExt> findUserList(UserQueryVO userQueryVO);
7.1.3.4 编写mapper映射文件
1 <select id="findUserList" parameterType="com.jxdd.mybatis.po.UserQueryVO" resultType="com.jxdd.mybatis.po.UserExt"> 2 SELECT * FROM USER WHERE sex=#{userExt.sex} AND username LIKE '%${userExt.username}%' 3 </select>
注意:入参的类型变为UserQueryVO、结果集的类型变为UserExt,#{}里面的参数变为UserQueryVO对象中的userExt属性的sex和username子属性。
7.1.3.5 编写测试代码
1 @Test 2 public void findUserListTset(){ 3 //创建SqlSession对象 4 SqlSession sqlSession = sqlSessionFactory.openSession(); 5 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 6 //构造UserQueryVO对象 7 UserQueryVO userQueryVO = new UserQueryVO(); 8 //构造UserExt对象 9 UserExt userExt = new UserExt(); 10 userExt.setSex("1"); 11 userExt.setUsername("张三"); 12 userQueryVO.setUserExt(userExt); 13 //调用mapper对象方法 14 List<UserExt> userList = userMapper.findUserList(userQueryVO); 15 System.out.println(userList); 16 //关闭连接 17 sqlSession.close(); 18 }
运行结果
DEBUG [main] - Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter. DEBUG [main] - PooledDataSource forcefully closed/removed all connections. DEBUG [main] - PooledDataSource forcefully closed/removed all connections. DEBUG [main] - PooledDataSource forcefully closed/removed all connections. DEBUG [main] - PooledDataSource forcefully closed/removed all connections. DEBUG [main] - Opening JDBC Connection DEBUG [main] - Created connection 235542568. DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@e0a1828] DEBUG [main] - ==> Preparing: SELECT * FROM USER WHERE sex=? AND username LIKE '%张三%' DEBUG [main] - ==> Parameters: 1(String) DEBUG [main] - <== Total: 2 [User [id=10, username=张三, sex=1, birthday=Thu Jul 10 00:00:00 CST 2014, address=北京市], User [id=24, username=张三丰, sex=1, birthday=null, address=北京市]] DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@e0a1828] DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@e0a1828] DEBUG [main] - Returned connection 235542568 to pool.
7.1.4 映射HashMap
同传递POJO对象一样,map的key相当于pojo的属性。
7.1.4.1 编写mapper接口
1 public User findUserByHashmap(HashMap<String, Object> hashMap);
7.1.4.2 映射文件
1 <!-- 传递hashmap综合查询用户信息 --> 2 <select id="findUserByHashmap" parameterType="java.util.HashMap" resultType="com.jxdd.mybatis.po.User"> 3 select * from user where id=#{id} and username like '%${username}%' 4 </select>
7.1.4.3 编写测试代码
1 @Test 2 public void findUserByHashmapTest(){ 3 //创建SqlSession对象 4 SqlSession sqlSession = sqlSessionFactory.openSession(); 5 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 6 HashMap<String, Object> map = new HashMap<String, Object>(); 7 map.put("id", 28); 8 map.put("username", "qt"); 9 User user = userMapper.findUserByHashmap(map); 10 System.out.println(user); 11 sqlSession.close(); 12 }
7.2 输出映射
7.2.1 resultType
7.2.1.1 使用方法
使用resultType进行结果映射时,查询的列名和映射的pojo属性名完全一致,该列才能映射成功.
如果查询的列名和映射的pojo属性名全部不一致,则不会创建pojo对象
如果查询的列名和映射的pojo属性名有一个一致,就会创建pojo对象
7.2.1.2 输出简单类型
当输出结果只有一列时,可以使用ResultType指定简单类型作为输出结果类型。
7.2.1.2.1 需求
查询用户总数,需要传入查询条件复杂,比如(用户信息、订单信息、商品信息)
7.2.1.2.2 mapper映射文件
1 <!-- 综合查询用户信息总数,需要传入查询条件复杂,比如(用户信息、订单信息、商品信息) --> 2 <select id="findUsersCount" parameterType="com.jxdd.mybatis.po.UserQueryVO" 3 resultType="int"> 4 SELECT count(1) FROM USER WHERE sex = #{userExt.sex} AND username LIKE '%${userExt.username}%' 5 </select>
7.2.1.2.3 编写mapper接口
1 //综合查询用户信息总数。学习:resultType输出简单类型 2 public int findUsersCount(UserQueryVO vo);
7.2.1.2.4 编写测试类
1 @Test 2 public void findUsersCountTest(){ 3 //创建SqlSession对象 4 SqlSession sqlSession = sqlSessionFactory.openSession(); 5 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 6 //构造UserQueryVO对象 7 UserQueryVO userQueryVO = new UserQueryVO(); 8 //构造UserExt对象 9 UserExt userExt = new UserExt(); 10 userExt.setSex("1"); 11 userExt.setUsername("张三"); 12 userQueryVO.setUserExt(userExt); 13 int count = userMapper.findUsersCount(userQueryVO); 14 System.out.println(count); 15 sqlSession.close(); 16 }
7.2.1.3 输出POJO单个对象和列表
参考 根据用户id查询用户信息 和 根据用户名称模糊查询用户列表
总结:同样的mapper映射文件,返回单个对象和对象列表时,mapper接口在生成动态代理的时候,会根据返回值的类型,决定调用selectOne方法还是selectList方法。
7.2.2 resultMap
resultMap可以进行高级结果映射(一对一,一对多映射)
7.2.2.1 使用方法
如果查询出来的列名和属性名不一致,通过定义一个resultMap将列名和pojo属性名之间作一个映射关系。
1.定义resultMap
2.使用resultMap作为statement的输出映射类型.
7.2.2.2 需求
把下面SQL的输出结果集进行映射
SELECT id id_,username username_,sex sex_ FROM USER WHERE id = 1
7.2.2.3 mapper映射文件
1 <!-- 2 [id]:定义resultMap的唯一标识 3 [type]:定义该resultMap最终映射的pojo对象 4 [id标签]:映射结果集的唯一标识列,如果是多个字段联合唯一,则定义多个id标签 5 [result标签]:映射结果集的普通列 6 [column]:SQL查询的列名,如果列有别名,则该处填写别名 7 [property]:pojo对象的属性名 8 --> 9 <resultMap type="com.jxdd.mybatis.po.User" id="userResultMap"> 10 <id column="id_" property="id"/> 11 <result column="username_" property="username"/> 12 <result column="sex_" property="sex"/> 13 </resultMap> 14 <!-- 根据ID查询用户信息(学习resultMap) --> 15 <select id="findUserByIdResultMap" parameterType="int" resultMap="userResultMap"> 16 SELECT id id_,username username_,sex sex_ FROM USER WHERE id = #{id} 17 </select>
7.2.2.4 mapper接口定义
1 //根据ID查询用户信息(学习resultMap) 2 public User findUserByIdResultMap(int id);
定义Statement使用resultMap映射结果集时,Mapper接口定义方法的返回值类型为mapper映射文件中resultMap的type类型。
7.2.2.5 测试代码
1 @Test 2 public void findUserByIdResultMapTest(){ 3 //创建SqlSession对象 4 SqlSession sqlSession = sqlSessionFactory.openSession(); 5 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 6 User user = userMapper.findUserByIdResultMap(1); 7 System.out.println(user); 8 sqlSession.close(); 9 }
7.3 动态sql
通过Mybatis提供的各种动态标签实现动态拼接sql,使得mapper映射文件在编写SQL时更加灵活,方便。常用动态SQL标签有:if、where、foreach
7.3.1 If、where标签
If标签:作为判断入参来使用的,如果符合条件,则把if标签体内的SQL拼接上。注意:用if进行判断是否为空时,不仅要判断null,也要判断空字符串‘’;
Where标签:会去掉条件中的第一个and符号
7.3.1.1 需求
用户信息综合查询列表statement的定义使用动态SQL。
7.3.1.2 映射文件
1 <!-- 综合查询用户信息,需要传入查询条件复杂,比如(用户信息、订单信息、商品信息) --> 2 <select id="findUsersByQueryVO" parameterType="com.jxdd.mybatis.po.UserQueryVO" 3 resultType="com.jxdd.mybatis.po.User"> 4 SELECT * FROM USER 5 <where> 6 <if test="userExt != null"> 7 <if test="userExt.sex != null and userExt.sex != ''"> 8 AND sex = #{userExt.sex} 9 </if> 10 <if test="userExt.username != null and userExt.username != ''"> 11 AND username LIKE '%${userExt.username}%' 12 </if> 13 </if> 14 </where> 15 </select>
7.3.1.3 mapper接口定义
1 //通过包装类来进行复杂的用户信息综合查询 2 public List<UserExt> findUsersByQueryVO(UserQueryVO userQueryVO);
7.3.1.4 测试代码
1 @Test 2 public void findUsersByQueryVOTest(){ 3 //创建SqlSession对象 4 SqlSession sqlSession = sqlSessionFactory.openSession(); 5 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 6 //构造UserQueryVO对象 7 UserQueryVO userQueryVO = new UserQueryVO(); 8 //构造UserExt对象 9 UserExt userExt = new UserExt(); 10 userExt.setUsername("qt"); 11 userQueryVO.setUserExt(userExt); 12 List<UserExt> list = userMapper.findUsersByQueryVO(userQueryVO); 13 System.out.println(list); 14 sqlSession.close(); 15 }
运行结果

7.3.2 SQL片段
Mybatis提供了SQL片段的功能,可以提高SQL的可重用性
7.3.2.1 定义sql片段
使用sql标签来定义一个SQL片段:
1 <!-- 定义sql片段 --> 2 <!-- 3 [sql标签]:定义一个sql片段 4 [id]: sql片段的唯一标识 5 建议: 6 1、SQL片段中的内容最好是以单表来定义 7 2、如果是查询字段,则不要写上SELECT 8 3、如果是条件语句,则不要写上WHERE 9 --> 10 <sql id="select_user_where"> 11 <if test="userExt != null"> 12 <if test="userExt.sex != null and userExt.sex != ''"> 13 AND sex = #{userExt.sex} 14 </if> 15 <if test="userExt.username != null and userExt.username != ''"> 16 AND username LIKE '%${userExt.username}%' 17 </if> 18 </if> 19 </sql>
7.3.2.2 引用sql片段
1 <!-- 综合查询用户信息,需要传入查询条件复杂,比如(用户信息、订单信息、商品信息) --> 2 <select id="findUsersByQueryVO" parameterType="com.jxdd.mybatis.po.UserQueryVO" 3 resultType="com.jxdd.mybatis.po.User"> 4 SELECT * FROM USER 5 <where> 6 <include refid="select_user_where"></include> 7 </where> 8 </select>
7.3.3 Foreach
向sql传递数组或List时,mybatis使用foreach解析数组里的参数并拼接到SQL中。
7.3.3.1 传递pojo对象中的List集合
在用户查询列表和查询总数的statement中增加多个id输入查询
7.3.3.2 定义pojo中的List的属性
1 public class UserQueryVO { 2 private UserExt userExt; 3 4 //id集合 5 private List<Integer> idList; 6 7 public List<Integer> getIdList() { 8 return idList; 9 } 10 11 public void setIdList(List<Integer> idList) { 12 this.idList = idList; 13 } 14 15 public UserExt getUserExt() { 16 return userExt; 17 } 18 19 public void setUserExt(UserExt userExt) { 20 this.userExt = userExt; 21 } 22 }
7.3.3.3 映射文件
1 <!-- 根据用户ID的集合查询用户列表(学习foreach标签之直接传ID集合) --> 2 <!-- 3 [foreach标签]:表示一个foreach循环 4 [collection]:集合参数的名称,如果是直接传入集合参数,则该处的参数名称只能填写[list]。 5 [item]:定义遍历集合之后的参数名称 6 [open]:开始遍历之前需要拼接的SQL串 7 [close]:结束遍历之后需要拼接的SQL串 8 [separator]:遍历出的每个对象之间需要拼接的字符 9 --> 10 <select id="findUsersByIdList" parameterType="java.util.List" resultType="com.jxdd.mybatis.po.User"> 11 SELECT * FROM USER 12 <where> 13 <if test="list != null and list.size > 0"> 14 <foreach collection="list" item="id" open="AND id IN (" close=")" separator=","> 15 #{id} 16 </foreach> 17 </if> 18 </where> 19 </select>
7.3.3.4 mapper接口
1 //根据用户ID的集合查询用户列表(学习foreach标签之直接传ID集合) 2 public List<User> findUsersByIdList (List<Integer> idList);
7.3.3.5 测试代码
1 @Test 2 public void findUsersCountFTest(){ 3 //创建SqlSession对象 4 SqlSession sqlSession = sqlSessionFactory.openSession(); 5 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); 6 //构造UserQueryVO对象 7 UserQueryVO userQueryVO = new UserQueryVO(); 8 List<Integer> idList = new ArrayList<Integer>(); 9 idList.add(1); 10 idList.add(10); 11 idList.add(16); 12 userQueryVO.setIdList(idList); 13 List<User> list = userMapper.findUsersByIdList(idList); 14 System.out.println(list); 15 sqlSession.close(); 16 }
mybatis与hibernate的区别及各自应用场景
Mybatis技术特点:
1、 通过直接编写SQL语句,可以直接对SQL进行性能的优化;
2、 学习门槛低,学习成本低。只要有SQL基础,就可以学习mybatis,而且很容易上手;
3、 由于直接编写SQL语句,所以灵活多变,代码维护性更好。
4、 不能支持数据库无关性,即数据库发生变更,要写多套代码进行支持,移植性不好。
5、 需要编写结果映射。
Hibernate技术特点:
1、 标准的orm框架,程序员不需要编写SQL语句。
2、 具有良好的数据库无关性,即数据库发生变化的话,代码无需再次编写。
3、 学习门槛高,需要对数据关系模型有良好的基础,而且在设置OR映射的时候,需要考虑好性能和对象模型的权衡。
4、 程序员不能自主的去进行SQL性能优化。
Mybatis应用场景:
需求多变的互联网项目,例如电商项目。
Hibernate应用场景:
需求明确、业务固定的项目,例如OA项目、ERP项目等。

浙公网安备 33010602011771号