Mybatis中的参数、返回值的深入
一、使用实体类的包装对象作为查询条件
定义一个类QueryVo:
public class QueryVo {
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
该类中有一个User类的属性。
现在要求用QueryVo作为条件进行查询,testFindByVo方法:
/**
* 测试使用QueryVo作为查询条件
*/
@Test
public void testFindByVo(){
QueryVo vo = new QueryVo();
User user = new User();
user.setUsername("%王%");
vo.setUser(user);
//5.执行查询方法
List<User> users = userDao.findUserByVo(vo);
for (User u : users){
System.out.println(u);
}
}
接口:
/**
* 根据queryVo中的条件查询用户
* @param vo
* @return
*/
List<User> findUserByVo(QueryVo vo);
xml:
注意的是这里需要用的mybatis的OGNL表达式,使用user.username来作为sql语句中的参数。
OGNL表达式:Object Graphic Navigation Language(对象 图 导航 语言)
它是通过对象的取值方法来获取数据。在写法上把get给省略了。
比如:我们过去用户的名称:
在类中的写法:user.getUsername();
OGNL表达式写法:user.username
为什么mybatis中,比如上面几个操作中,我们一般都是直接写username,而不用user.username呢?因为在parameterType中已经提供了属性所属的类,所以此时不需要写对象名
<!--根据queryVo的条件查询用户-->
<select id="findUserByVo" parameterType="com.itheima.domain.QueryVo" resultType="com.itheima.domain.User">
select * from user where username like #{user.username}
</select>
结果:
二、调整实体类属性解决增和改方法的报错
当我们查询的时候,返回的值需要封装到我们的实体类中,如果我们实体类中的属性和数据库中的列名不一致,就会导致报错。
比如,我数据库中的列名为:id,username,address,sex,birthday。而我User实体类中的属性名为:userId,userName,userAddress,userSex,userBirthday。
如果是这样执行增删改方法就一定会报错:
但是当我们运行findAll方法时,却不会报错,但是执行的结果有点问题:
我们发现除了userName这一栏有属性,其他的都为null,这是因为mysql在windows系统中是不区分大小写的,所以我们实体类中的userName和数据库中的username可以对应的上,但是其他属性是完全不同,所以无法对应。另外mysql在linux上是严格区分大小写的,而一般数据库都会部署在linux服务器上,所以还是要解决这个问题。
解决的思路无非就是让数据库中的列名和我们实体类中的属性名对应上
方法有两种:
1)在sql语句中取别名
原本的sql语句:
<!--查询所有-->
<select id="findAll" resultType="com.itheima.domain.User">
select * from user;
</select>
更新sql语句,给列名取别名:
<!--查询所有-->
<select id="findAll" resultType="com.itheima.domain.User">
select id as userId,username as userName,address as userAddress,sex as userSex,birthday as userBirthday from user;
</select>
运行结果没有任何问题:
2)采用在xml中配置的方式
在mapper中加多一条resultMap的标签:
<!--配置查询结果的列名和实体类的属性名的对应关系-->
<resultMap id="userMap" type="com.itheima.domain.User">
<!--主键字段的对应-->
<id property="userId" column="id"></id>
<!--非主键字段的对应-->
<result property="userName" column="name"></result>
<result property="userAddress" column="address"></result>
<result property="userSex" column="sex"></result>
<result property="userBirthday" column="birthday"></result>
</resultMap>
当有了这一条标签后,在查询所有的实现标签里使用它,使用resultMap代替原本的resultType。此时可以使用简单的sql语句完成查询。
<!--查询所有-->
<select id="findAll" resultMap="userMap">
select * from user;
</select>
结果:
第一种方法在执行的效率上来说是最高的,它直接在mysql的语句的层面上解决了问题,但是在开发和维护时,需要对每一条sql语句进行取别名操作,开发效率比较低;
第二种方法会多解析一段xml,所以在执行效率上没有第一种方法快,但是好处是开发效率变快了,我们只需要在最开始配置一次,后面所有的方法都可以直接使用。
两种方法各有利弊,酌情选择。