一、引言
在日常开发用到mybatis时,因为实际的开发业务场景很复杂,不论是输入的查询条件,还是返回的结果,经常是需要根据业务来定制,这个时候我们就需要自己来定义一些输入和输出映射
二、parameterType(输入映射)
输入映射是在映射文件中通过parameterType指定输入参数的类型,类型可以是简单类型、hashmap、pojo的包装类型,当我们去查询用户时,有些字段基本不会用作查询条件,还有一些时候我们需要连表查询,那么这个时候我们可以用到包装类。
新建pojo包,定义包装类:
publicclass QueryVo {
//pojoprivate User user;
public User getUser() {
return user;
}
publicvoid setUser(User user) {
this.user = user;
}
}
将UserMapper.xml文件移至com.yuanqinnan.mapper包中,并增加一个查询方法
<select id="queryByQo" parameterType="com.yuanqinnan.pojo.QueryVo" resultType="com.yuanqinnan.model.User"> SELECT * from user where username like '%${user.username}%'</select>
UserMapper中增加接口:
List<User> queryByQo(QueryVo queryVo);
结构如图:
将SqlMapConfig.xml 中其他的配置恢复原先配置,引入mapper方式进行修改
<mappers><package name="com.yuanqinnan.mapper"/></mappers>
测试方法:
@Testpublicvoid testQueryUserByUsername2() {
// 获取sqlSession,和spring整合后由spring管理SqlSession sqlSession =this.sqlSessionFactory.openSession();
// 从sqlSession中获取Mapper接口的代理对象UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 执行查询方法QueryVo queryVo=new QueryVo();
User user=new User();
user.setUsername("张");
queryVo.setUser(user);
List list = userMapper.queryByQo(queryVo);
for (User user2 : list) {
System.out.println(user2);
}
// 和spring整合后由spring管理 sqlSession.close();
}
原以为会很顺利的出现结果,结果一直报错:invalid bound statement (not found),这个错误是找不到相应sql,可是明明路径和sql都是对的,最后竟然发现是需要在pom.xml文件中配置resource,不然mapper.xml文件就会被漏掉,这种错误真是太恼火了,pom加上配置:
<build><resources><resource><directory>src/main/java</directory><includes><include>**/*.properties</include><include>**/*.xml</include></includes><filtering>false</filtering></resource></resources></build>
得到测试结果:
输入映射比较简单,一般不会使用包装类,而是根据需要的条件去设置字段比较好
三、resultType(输出类型)
输出类型有简单类型,pojo类,pojo列表,pojol类和列表在前面的例子中都有演示,下面看一个简单类型的
新增方法:
<select id="queryUserCount" resultType="int"> select count(*) from user</select>
接口:
intqueryUserCount();
测试:
@Testpublicvoid testQueryUserCount() {
// 获取sqlSession,和spring整合后由spring管理SqlSession sqlSession =this.sqlSessionFactory.openSession();
// 从sqlSession中获取Mapper接口的代理对象UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
// 执行查询方法intcount= userMapper.queryUserCount() ;
System.out.println(count);
// 和spring整合后由spring管理 sqlSession.close();
}
结果:10
四、resultMap
resultType可以指定将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功。
如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系 ,resultMap实质上还需要将查询结果映射到pojo对象中。
resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询。
下面通过例子来说明:
先新增一张订单表,sql如下:
DROPTABLEIFEXISTS`order`;CREATETABLE `order` (
`id` int(11)NOTNULL AUTO_INCREMENT,
`user_id`int(11)NOTNULLCOMMENT'下单用户id',
`number`varchar(32)NOTNULLCOMMENT'订单号',
`createtime` datetimeNOTNULLCOMMENT'创建订单时间',
`note` varchar(100)DEFAULTNULLCOMMENT'备注',
PRIMARYKEY (`id`),
KEY`FK_order_1` (`user_id`),
CONSTRAINT`FK_order_id`FOREIGNKEY(`user_id`)REFERENCES`user` (`id`)ONDELETENO ACTIONONUPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=6DEFAULTCHARSET=utf8;-- ------------------------------ Records of order-- ----------------------------INSERTINTO`order`VALUES('3','1','1000010','2015-02-04 13:22:35',null);INSERTINTO`order`VALUES('4','1','1000011','2015-02-03 13:22:41',null);INSERTINTO`order`VALUES('5','10','1000012','2015-02-12 16:13:23',null);
实体:
publicclass Order {
// 订单idprivateint id;
// 用户idprivate Integer userId;
// 订单号private String number;
// 订单创建时间private Date createtime;
// 备注private String note;
publicint getId() {
return id;
}
public Integer getUserId() {
return userId;
}
public String getNumber() {
return number;
}
public Date getCreatetime() {
return createtime;
}
public String getNote() {
return note;
}
publicvoidsetId(int id) {
this.id = id;
}
publicvoid setUserId(Integer userId) {
this.userId = userId;
}
publicvoid setNumber(String number) {
this.number = number;
}
publicvoid setCreatetime(Date createtime) {
this.createtime = createtime;
}
publicvoid setNote(String note) {
this.note = note;
}
@Override
public String toString() {
return"Order{" + "id=" + id + ", userId=" + userId + ", number='" + number + '\'' + ", createtime=" + createtime + ", note='" + note + '\'' + '}';
}
}
新增OrderMapper.xml:
<?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="com.yuanqinnan.mapper.OrderMapper"><!-- 查询所有的订单数据 --><select id="queryOrderAll" resultType="com.yuanqinnan.model.Order"> SELECT id, user_id,
number,
createtime, note FROM `order`
</select></mapper>
新增OrderMapper接口
publicinterface OrderMapper {
List queryOrderAll();
}
测试:
@Testpublicvoid testQueryAll() {
// 获取sqlSessionSqlSession sqlSession =this.sqlSessionFactory.openSession();
// 获取OrderMapperOrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
// 执行查询List list = orderMapper.queryOrderAll();
for (Order order : list) {
System.out.println(order);
}
}
结构如图:
结果:
发现userId为null,用resultMap解决,修改OrderMapper.xml,定义resultMap
<?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="com.yuanqinnan.mapper.OrderMapper"><!-- resultMap最终还是要将结果映射到pojo上,type就是指定映射到哪一个pojo --><!-- id:设置ResultMap的id --><resultMap type="com.yuanqinnan.model.Order" id="orderResultMap"><!-- 定义主键 ,非常重要。如果是多个字段,则定义多个id --><!-- property:主键在pojo中的属性名 --><!-- column:主键在数据库中的列名 --><id property="id" column="id"/><!-- 定义普通属性 --><result property="userId" column="user_id"/><result property="number" column="number"/><result property="createtime" column="createtime"/><result property="note" column="note"/></resultMap><!-- 查询所有的订单数据 --><select id="queryOrderAll" resultType="com.yuanqinnan.model.Order"> SELECT id, user_id,
number,
createtime, note FROM `order`
</select><select id="queryOrderAll2" resultMap="orderResultMap"> SELECT id, user_id,
number,
createtime, note FROM `order`
</select></mapper>
增加接口:
List<Order> queryOrderAll2();
测试方法:
@Testpublicvoid testQueryAll2() {
// 获取sqlSessionSqlSession sqlSession =this.sqlSessionFactory.openSession();
// 获取OrderMapperOrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);
// 执行查询List list = orderMapper.queryOrderAll2();
for (Order order : list) {
System.out.println(order);
}
}
结果: