Mybatis的参数深入
- Mybatis的映射文件其实就是与DAO相对应,因为DAO中的方法有输入参数及返回结果,那么在Mybatis的映射文件中自然也就有与之对应的参数和返回结果。
- 在Mybatis的映射文件中参数用parameterType来代表,它的值可以是基本类型,也可以是包装的对象,在Mybatis的映射文件中返回结果用resultType或resultMap来代表。
Mybatis的参数
一. parameterType(输入类型)
1. 传递简单类型
2. 传递pojo对象
Mybatis使用ognl表达式解析对象字段的值,#{}或者${}括号中的值为pojo属性名称。
3. 传递pojo包装对象
开发中通过pojo传递查询条件 ,查询条件是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数。
Pojo类中包含pojo。
需求:根据用户名查询用户信息,查询条件放到QueryVo的user属性中。
3.1 QueryVo封装
public class QueryVo { private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; } }
3.2 UserMapper接口
在UserMapper接口中加入如下方法:
/*** * 根据用户名查询用户 * @param vo * @return */ User findByVo(QueryVo vo);
3.3 UserMapper.xml
修改UserMapper.xml文件
<select id="findByVo" parameterType="com.itheima.domain.QueryVo" resultType="com.itheima.domain.User"> SELECT * FROM user WHERE username = #{user.username} </select>
如果我们使用的是包装类作为参数,比如这个示例的QueryVo类作为findByVo()方法的参数,那么在使用时,因为QueryVo类中有一个User类的user对象,而这个user对象中才能找到username属性,所以我们在访问属性时,就使用OGNL表达式才访问对象的属性。
3.4 测试包装类作为参数
添加测试方法,如下:
/*** * 测试QueryVo */ @Test public void testQueryVo(){ QueryVo vo = new QueryVo(); User user = new User(); user.setUsername("张三"); vo.setUser(user); User userInfo = userMapper.findByVo(vo); System.out.println(userInfo); }
Mybatis的输出结果封装
二 . resultType(输出类型)
1 .输出简单类型
修改UserMapper接口,增加如下方法
/*** * 查询总数 * @return */ int findUserCount();
修改UserMapper.xml,增加如下方法:
<!--简单类型--> <select id="findUserCount" resultType="java.lang.Integer"> SELECT COUNT(*) FROM user </select>
测试代码
/*** * 返回简单数据类型 */ @Test public void testFindUserCount(){ int count = userMapper.findUserCount(); }
输出简单类型必须查询出来的结果集有一条记录,最终将第一个字段的值转换为输出类型。
2. 输出Pojo对象
3. 输出Pojo列表
3.1 resultMap结果类型
- resultType可以指定pojo将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功。
- 如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系 ,resultMap实质上还需要将查询结果映射到pojo对象中。
- resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询。
3.2 UserMapper.xml定义
需求:如果返回的列名与实体类的属性不一致时,我们就不能封装结果集到指定的实体对象。
SQL:select id id_,username username_ ,birthday birthday_ ,sex sex_ ,address address_ from user where username='传智播客'
通过改别名的方式,现在返回结果集的列名已经与User类的属性名不相同了。
<!--findByVo--> <select id="findByVo" parameterType="com.itheima.domain.QueryVo" resultType="com.itheima.domain.User"> SELECT id id_,username username_ ,birthday birthday_ ,sex sex_ ,address address_ FROM user WHERE username = #{user.username} </select>
我们再次运行程序,发现出错如下:
org.apache.ibatis.exceptions.PersistenceException: ### Error querying database. Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure Last packet sent to the server was 1 ms ago. ### The error may exist in com/itheima/mapper/UserMapper.xml ### The error may involve com.itheima.mapper.UserMapper.findByVo ### The error occurred while executing a query ### Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
这个错误就是我们返回结果集的列名与对应User的属性名不对应造成的,使用resultMap可以将建立起结果集的列与实体类的属性名之间的映射,这样就可以解决列名与属性名不相同的问题。
3.3 定义resultMap
由于上边的mapper.xml中sql查询列和Users.java类属性不一致,需要定义resultMap:userListResultMap将sql查询列和Users.java类属性对应起来
<!--UserResultMap--> <resultMap id="UserResultMap" type="com.itheima.domain.User"> <id column="id_" property="id" /> <result column="username_" property="username" /> <result column="birthday_" property="birthday" /> <result column="sex_" property="sex" /> <result column="address_" property="address" /> </resultMap> <!--findByVo--> <select id="findByVo" parameterType="com.itheima.domain.QueryVo" resultMap="UserResultMap"> SELECT id id_,username username_ ,birthday birthday_ ,sex sex_ ,address address_ FROM user WHERE username = #{user.username} </select>
- < id />此属性表示查询结果集的唯一标识,非常重要。如果是多个字段为复合唯一约束则定义多个 。
- property:表示User类的属性。
- column:表示sql查询出来的字段名。
- column和property放在一块儿表示将sql查询出来的字段映射到指定的pojo类属性上。
- < result />普通结果,即pojo的属性。
3.4 测试效果
==> Preparing: SELECT id id_,username username_ ,birthday birthday_ ,sex sex_ ,address address_ FROM user WHERE username = ? ==> Parameters: 张三(String) <== Total: 1User{id=42, username='张三', birthday=Fri Mar 02 15:09:37 CST 2018, sex='女', address='北京金燕龙'}