本节内容:
- 输入参数映射
- 输出映射
- resultMap
Mapper.xml映射文件中定义了操作数据库的sql,每个sql是一个statement,映射文件是mybatis的核心。
一、环境准备
复制昨天的模块,然后粘贴,把名字改掉。具体操作如下:
然后把原来模块下的lib和src目录复制到新的模块下。
将src目录标记为源代码目录。
二、输入参数映射(parameterType)
1. 传递简单类型
参考上一篇文章。
使用#{}占位符,或者${}进行sql拼接。
2. 传递pojo对象
参考上一篇文章。
Mybatis使用ognl表达式解析对象字段的值,#{}或者${}括号中的值为pojo属性名称。
3. 传递pojo包装对象
开发中通过可以使用pojo传递查询条件。
查询条件可能是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如查询用户信息的时候,将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数。
包装对象:Pojo类中的一个属性是另外一个pojo。
需求:根据用户名模糊查询用户信息,查询条件放到QueryVo的user属性中。
(1)编写QueryVo
QueryVo.java
package com.wisedu.mybatis.pojo; import java.io.Serializable; public class QueryVo implements Serializable { //序列化,对象转成二进制进行传输。 private static final long serialVersionUID = 1L; // private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; } }
(2)sql语句
在UserMapper.xml中配置sql,如下:
<select id="queryUserByQueryVo" parameterType="QueryVo" resultType="com.wisedu.mybatis.pojo.User"> SELECT * FROM `user` WHERE username LIKE "%"#{user.username}"%" <!-- user对象被封装在QueryVo中 --> </select>
(3)Mapper接口
在UserMapper接口中添加方法,如下:
public List<User> queryUserByQueryVo(QueryVo vo);
(4)测试方法
在MybatisMapperTest.ajva增加测试方法,如下:
@Test public void testMapperQueryVo() throws Exception { //加载核心配置文件 String resource = "sqlMapConfig.xml"; InputStream in = Resources.getResourceAsStream(resource); //创建SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); // 获取sqlSession,和spring整合后由spring管理 SqlSession sqlSession = sqlSessionFactory.openSession(); //SqlSEssion会帮我生成一个实现类 (需要我们给接口,它帮我们生成实现类,返回给我们的还是接口) UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User user = new User(); user.setUsername("五"); QueryVo vo = new QueryVo(); vo.setUser(user); List<User> users = userMapper.queryUserByQueryVo(vo); for (User u : users) { System.out.println(u); } // 和spring整合后由spring管理 sqlSession.close(); }
(5)执行测试方法
DEBUG [main] - ==> Preparing: SELECT * FROM `user` WHERE username LIKE "%"?"%" DEBUG [main] - ==> Parameters: 五(String) DEBUG [main] - <== Total: 2 User [id=1, username=王五, sex=2, birthday=null, address=null] User [id=26, username=王五, sex=null, birthday=null, address=null]
三、输出类型(resultType)
1. 输出简单类型
需求:查询用户表数据条数,sql:SELECT count(*) FROM `user`
(1)Mapper.xml文件
在UserMapper.xml中配置sql,如下图:
<!--输出简单类型--> <select id="queryUserCount" resultType="int"> SELECT count(*) FROM `user` </select>
(2)Mapper接口
在UserMapper添加方法,如下图:
//查询数据条数 public Integer queryUserCount();
(3)测试方法
在MybatisMapperTest.ajva增加测试方法,如下:
@Test public void testCount() throws Exception { //加载核心配置文件 String resource = "sqlMapConfig.xml"; InputStream in = Resources.getResourceAsStream(resource); //创建SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); // 获取sqlSession,和spring整合后由spring管理 SqlSession sqlSession = sqlSessionFactory.openSession(); //SqlSEssion会帮我生成一个实现类 (需要我们给接口,它帮我们生成实现类,返回给我们的还是接口) UserMapper userMapper = sqlSession.getMapper(UserMapper.class); Integer count = userMapper.queryUserCount(); System.out.println(count); // 和spring整合后由spring管理 sqlSession.close(); }
(4)执行测试方法
DEBUG [main] - ==> Preparing: SELECT count(*) FROM `user` DEBUG [main] - ==> Parameters: DEBUG [main] - <== Total: 1 9
2. 输出pojo对象
参见上一篇博客。
3. 输出pojo列表
参见上一篇博客。
四、resultMap
resultType可以指定将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功。
如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系 ,resultMap实质上还需要将查询结果映射到pojo对象中。
resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询。
【需求】:查询订单表order的所有数据,sql:SELECT id, user_id, number, createtime, note FROM `order`
1. 编写pojo对象
数据库order表:
CREATE TABLE `orders` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user_id` int(11) NOT NULL COMMENT ‘下单用户id‘, `number` varchar(32) NOT NULL COMMENT ‘订单号‘, `createtime` datetime NOT NULL COMMENT ‘创建订单时间‘, `note` varchar(100) DEFAULT NULL COMMENT ‘备注‘, PRIMARY KEY (`id`), KEY `FK_orders_1` (`user_id`), CONSTRAINT `FK_orders_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;
Order.java
package com.wisedu.mybatis.pojo; import java.io.Serializable; import java.util.Date; public class Orders implements Serializable{ private static final long serialVersionUID = 1L; private Integer id; private Integer userId; private String number; private Date createtime; private String note; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Integer getUserId() { return userId; } public void setUserId(Integer userId) { this.userId = userId; } public String getNumber() { return number; } public void setNumber(String number) { this.number = number == null ? null : number.trim(); } public Date getCreatetime() { return createtime; } public void setCreatetime(Date createtime) { this.createtime = createtime; } public String getNote() { return note; } public void setNote(String note) { this.note = note == null ? null : note.trim(); } @Override public String toString() { return "Orders{" + "id=" + id + ", userId=" + userId + ", number=‘" + number + ‘\‘‘ + ", createtime=" + createtime + ", note=‘" + note + ‘\‘‘ + ‘}‘; } }
2. Mapper.xml文件
创建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.wisedu.mybatis.mapper.OrderMapper"> <!-- 查询所有的订单数据 --> <select id="queryOrdersAll" resultType="Orders"> SELECT id, user_id, number, createtime, note FROM `orders` </select> </mapper>
3. Mapper接口
编写接口如下:
package com.wisedu.mybatis.mapper; import com.wisedu.mybatis.pojo.Orders; import java.util.List; public interface OrderMapper { //查询所有订单 List<Orders> queryOrdersAll(); }
4. 测试方法
编写测试方法如下:
//查询订单表orders的所有数据 @Test public void testResultMap() throws Exception { //加载核心配置文件 String resource = "sqlMapConfig.xml"; InputStream in = Resources.getResourceAsStream(resource); //创建SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); // 获取sqlSession,和spring整合后由spring管理 SqlSession sqlSession = sqlSessionFactory.openSession(); //SqlSEssion会帮我生成一个实现类 (需要我们给接口,它帮我们生成实现类,返回给我们的还是接口) OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class); List<Orders> orderses = orderMapper.queryOrdersAll(); for (Orders order: orderses) { System.out.println(order); } // 和spring整合后由spring管理 sqlSession.close(); }
执行测试方法,查看控制台日志:
DEBUG [main] - ==> Preparing: SELECT id, user_id, number, createtime, note FROM `orders` DEBUG [main] - ==> Parameters: DEBUG [main] - <== Total: 3 Orders{id=3, userId=null, number=‘1000010‘, createtime=Wed Feb 04 13:22:35 CST 2015, note=‘null‘} Orders{id=4, userId=null, number=‘1000011‘, createtime=Tue Feb 03 13:22:41 CST 2015, note=‘null‘} Orders{id=5, userId=null, number=‘1000012‘, createtime=Thu Feb 12 16:13:23 CST 2015, note=‘null‘}
发现userId为null。
解决方案:使用resultMap
5. 使用resultMap
由于上边的mapper.xml中sql查询列(user_id)和Order类属性(userId)不一致,所以查询结果不能映射到pojo中。
需要定义resultMap,把orderResultMap将sql查询列(user_id)和Order类属性(userId)对应起来。
修改OrderMapper.xml,如下:
<!-- resultMap最终还是要将结果映射到pojo上,type就是指定映射到哪一个pojo --> <!-- id:设置ResultMap的id --> <resultMap type="Orders" 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" /> <!--当然可以只写属性名和列名不一样的,一样的可以省略。id一样也可以省略--> </resultMap> <!-- 查询所有的订单数据 --> <select id="queryOrdersAll" resultMap="orderResultMap"> SELECT id, user_id, number, createtime, note FROM `orders` </select>
再次执行测试方法,查看控制台日志:
DEBUG [main] - ==> Preparing: SELECT id, user_id, number, createtime, note FROM `orders` DEBUG [main] - ==> Parameters: DEBUG [main] - <== Total: 3 Orders{id=3, userId=1, number=‘1000010‘, createtime=Wed Feb 04 13:22:35 CST 2015, note=‘null‘} Orders{id=4, userId=1, number=‘1000011‘, createtime=Tue Feb 03 13:22:41 CST 2015, note=‘null‘} Orders{id=5, userId=10, number=‘1000012‘, createtime=Thu Feb 12 16:13:23 CST 2015, note=‘null‘}