本篇内容,紧接上一篇内容 Mybatis学习笔记一
输入映射和输出映射
传递简单类型和pojo类型上篇已介绍过,下面介绍一下包装类型。
传递pojo包装对象
开发中通过可以使用pojo传递查询条件。查询条件可能是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如查询用户信息的时候,将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数。包装对象即Pojo类中的一个属性是另外一个pojo。
演示:根据用户名模糊查询用户信息,查询条件放到QueryVo的user属性中。
上一篇的SqlMapConfig.xml:(就是mybatis配置xml):
"1.0" encoding="UTF-8" ?> DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">"cn.itcast.mybatis.po.User" alias="User" /> "com.yyb.pojo.QueryVo" alias="QueryVo" /> "com.yyb.pojo.Orders" alias="Orders" /> default="development"> "development"> "JDBC" /> "POOLED"> "driver" value="com.mysql.jdbc.Driver" /> "url" value="jdbc:mysql://192.168.1.20:3306/test?" /> "username" value="root" /> "password" value="root123" /> "mapper/UserMapper.xml"/> "mapper/orderMapper.xml"/>
1、编写QueryVo
package com.yyb.pojo; import java.io.Serializable; /** * Created by Administrator on 2017/8/16. */ public class QueryVo implements Serializable{ public User getUser() { return user; } public void setUser(User user) { this.user = user; } private User user; }
2、userMapper配置
3.、userMapper接口中添加
ListfindByQueryVo(QueryVo vo);
4、测试类
@org.junit.Test public void func2() throws Exception { //加载核心配置文件 String resource = "sqlMapConfig.xml"; InputStream in = Resources.getResourceAsStream(resource); //创建SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); //创建SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); //SqlSEssion帮我生成一个实现类 (给接口) UserMapper userMapper = sqlSession.getMapper(UserMapper.class); QueryVo vo=new QueryVo(); User u=new User(); u.setUsername("五"); vo.setUser(u); Listus = userMapper.findByQueryVo(vo); for (User use:us) { System.out.println(use); } }
resultType(输出类型)
1、输出简单类型。示例:查询用户表数据条数
在userMapper.xml中添加如下代码:
在userMapper接口中添加以下代码:
int findUserCount();
测试方法
@org.junit.Test public void func3() throws Exception { //加载核心配置文件 String resource = "sqlMapConfig.xml"; InputStream in = Resources.getResourceAsStream(resource); //创建SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); //创建SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); //SqlSEssion帮我生成一个实现类 (给接口) UserMapper userMapper = sqlSession.getMapper(UserMapper.class); int count = userMapper.findUserCount(); System.out.println(count); }
注意:输出简单类型必须查询出来的结果集有一条记录,最终将第一个字段的值转换为输出类型。
2、输出pojo对象,参考上篇
3、输出pojo列表,参考上篇
4、resultMap
resultType可以指定将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功。
如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系 ,resultMap实质上还需要将查询结果映射到pojo对象中。
resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询。
示例:查询订单表order的所有数据
添加Order实体
package com.yyb.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(); } }
添加orderMapper.xml,在其中添加如下代码:
添加orderMapper接口,在其中添加以下代码:
package com.yyb.mapper; import com.yyb.pojo.Orders; import java.util.List; public interface OrderMapper { ListqueryOrderList(); }
测试类
package com.yyb.test; import com.yyb.mapper.OrderMapper; import com.yyb.pojo.Orders; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.InputStream; import java.util.List; /** * Created by Administrator on 2017/8/16. */ public class TestOrder { @org.junit.Test public void func1() throws Exception { //加载核心配置文件 String resource = "sqlMapConfig.xml"; InputStream in = Resources.getResourceAsStream(resource); //创建SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); //创建SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); //SqlSEssion帮我生成一个实现类 (给接口) OrderMapper userMapper = sqlSession.getMapper(OrderMapper.class); Listorders = userMapper.queryOrderList(); for (Orders o:orders) { System.out.println(o); } } }
由于sql查询列(user_id)和Order类属性(userId)不一致,所以查询结果不能映射到pojo中。需要定义resultMap,把orderResultMap将sql查询列(user_id)和Order类属性(userId)对应起来。
动态sql
通过mybatis提供的各种标签方法实现动态拼接sql。
示例:根据性别和名字查询用户
在userMapper接口中添加如下代码:
ListfindUserByWhere(User user);
在userMapper.xml中添加如下代码:
测试方法如下:
@org.junit.Test public void func4() throws Exception { //加载核心配置文件 String resource = "sqlMapConfig.xml"; InputStream in = Resources.getResourceAsStream(resource); //创建SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); //创建SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); //SqlSEssion帮我生成一个实现类 (给接口) UserMapper userMapper = sqlSession.getMapper(UserMapper.class); User u=new User(); u.setUsername("张"); //u.setSex("1"); Listus = userMapper.findUserByWhere(u); for (User use:us) { System.out.println(use); } }
If标签
注意字符串类型的数据需要要做不等于空字符串校验。
WHERE 1=1AND sex = #{sex} AND username LIKE "%"#{username}"%"
Where标签
上面的sql还有where 1=1 这样的语句,很麻烦,可以使用where标签进行改造,where标签可以自动添加where,同时处理sql语句中第一个and关键字。
改造UserMapper.xml,如下:
Sql片段
Sql中可将重复的sql提取出来,使用时用include引用即可,最终达到sql重用的目的。
把上面例子中的id, username, birthday, sex, address提取出来,作为sql片段,如下:
SELECT id, username, birthday, sex, address FROM user
如果要使用别的Mapper.xml配置的sql片段,可以在refid前面加上对应的Mapper.xml的namespace,例如下图
foreach标签
向sql传递数组或List,mybatis使用foreach解析。
示例:根据多个id查询用户信息
添加接口 findUserByIds
改造QueryVo
package com.yyb.pojo; import java.io.Serializable; import java.util.List; /** * Created by Administrator on 2017/8/16. */ public class QueryVo implements Serializable{ private User user; ListidsList; Integer[] ids; public User getUser() { return user; } public void setUser(User user) { this.user = user; } public List getIdsList() { return idsList; } public void setIdsList(List idsList) { this.idsList = idsList; } public Integer[] getIds() { return ids; } public void setIds(Integer[] ids) { this.ids = ids; } }
UserMapper.xml文件
测试方法:
@org.junit.Test public void func5() throws Exception { //加载核心配置文件 String resource = "sqlMapConfig.xml"; InputStream in = Resources.getResourceAsStream(resource); //创建SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); //创建SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); //SqlSEssion帮我生成一个实现类 (给接口) UserMapper userMapper = sqlSession.getMapper(UserMapper.class); QueryVo vo=new QueryVo(); Listlist=new ArrayList<>(); list.add(16); list.add(24); list.add(30); vo.setIdsList(list); List us = userMapper.findUserByIds(vo); for (User use:us) { System.out.println(use); } }
关联查询
商品订单数据模型
方式一:定义专门的pojo类作为输出类型,其中定义了sql查询结果集所有的字段(继承现有pojo)。此方法较为简单,企业中使用普遍。
下面介绍方式二,使用resultMap,定义专门的resultMap用于映射一对一查询结果。
一对一查询
示例:查询所有订单信息,关联查询下单用户信息。
注意:因为一个订单信息只会是一个人下的订单,所以从查询订单信息出发关联查询用户信息为一对一查询。如果从用户信息出发查询用户下的订单信息则为一对多查询,因为一个用户可以下多个订单。
在OrderMapper添加接口 List
在Order类中添加如下代码:
//在Order类中加入User属性,user属性中用于存储关联查询的用户信息,因为订单关联查询用户是一对一关系,所以这里使用单个User对象存储关联查询的用户信息。
private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; }
在OrderMapper.xml中添加如下代码:
测试代码:
@org.junit.Test public void func2() throws Exception { //加载核心配置文件 String resource = "sqlMapConfig.xml"; InputStream in = Resources.getResourceAsStream(resource); //创建SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); //创建SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); //SqlSEssion帮我生成一个实现类 (给接口) OrderMapper userMapper = sqlSession.getMapper(OrderMapper.class); Listorders = userMapper.queryOrderUser(); for (Orders o:orders) {//打断点调试查看user对象的值 System.out.println(o); } }
一对多查询
案例:查询所有用户信息及用户关联的订单信息。
用户信息和订单信息为一对多关系。
修改pojo类,在User类中加入List
private ListlsOrders; public List getLsOrders() { return lsOrders; } public void setLsOrders(List lsOrders) { this.lsOrders = lsOrders; }
在userMapper接口中添加如下接口: List
在UserMapper.xml添加如下代码:
测试代码如下:
@org.junit.Test public void func6() throws Exception { //加载核心配置文件 String resource = "sqlMapConfig.xml"; InputStream in = Resources.getResourceAsStream(resource); //创建SqlSessionFactory SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in); //创建SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); //SqlSEssion帮我生成一个实现类 (给接口) UserMapper userMapper = sqlSession.getMapper(UserMapper.class); Listus = userMapper.findUserOrders(); for (User u:us) { System.out.println(u); } }