1.输入和输出映射
Mapper.xml映射文件中定义了操作数据库的sql,每个sql是一个statement,映射文件是mybatis的核心。下面主要学习 使用包装对象传递输入参数
1. 输入映射(就是映射文件中可以传入哪些参数类型)
1)基本类型
2)pojo类型 (持久对象,可以看成是与数据库中的表相映射的java对象)
3)VO类型 (抽象出的业务对象,可以和表对应,也可以不)
2. 输出映射(返回的结果集可以有哪些类型)
1)基本类型
2)pojo类型
3)List类型
1.1 输入类型为包装类:
需求:根据用户名查询用户信息,查询条件放到QueryVo的user属性中:
1.1.1 查询条件包装到类QueryVo中:
public class QueryVo { private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; } }
1.1.2 mapper文件 (UserMapper.xml)
<!-- 使用包装类型查询用户 使用ognl从对象中取属性值,如果是包装对象可以使用.操作符来取内容部的属性 --> <select id="findUserByQueryVo" parameterType="cn.itcast.pojo.QueryVO" resultType="cn.itcast.pojo.User"> SELECT * FROM user where username like '%${user.username}%' </select>
1.1.3 mapper接口 (UserMapper.java)
public interface UserMapper { public List<User> findUserByQueryVo(QueryVO queryVO) throws Exception; }
1.1.4 测试
@Test public void TestFindUserByQueryVO() throws Exception{ //获取session SqlSession session = sqlSessionFactory.openSession(); //获取mapper接口的代理对象 UserMapper userMapper = session.getMapper(UserMapper.class); QueryVO queryVO = new QueryVO(); User user = new User(); queryVO.setUser(user); //调用代理对象方法 List<User> list = userMapper.findUserByQueryVo(queryVO); System.out.println(list); //关闭session session.close(); }
1.2 resultMap
resultType可以指定pojo将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功。
如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系 ,resultMap实质上还需要将查询结果映射到pojo对象中。
resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询。
补充:在核心配置文件SqlMapConfig.xml中可以定义别名,这样在映射文件中应用某个包的类可以直接使用别名。
<typeAliases> <!-- 定义单个pojo类别名 type:类的全路劲名称 alias:别名 --> <!-- <typeAlias type="cn.itheima.pojo.User" alias="user"/> --> <!-- 使用包扫描的方式批量定义别名。扫描整个包下的类,别名为类名(首字母大写或小写都可以)--> <package name="cn.ztt.pojo"/> </typeAliases>
1.2.1 Mapper.xml定义
假设数据库中参数都是id_ , username_ 这样的和java类中不一样
<!-- 封装sql条件,封装后可以重用. id:是这个sql条件的唯一标识 --> <sql id="query_user_where"> <if test="id_!=null and id_!=''"> and id_=#{id} </if> <if test="username_!=null and username_!=''"> and username_ like '%${username}%' </if> <if test="sex_!=null and sex_!=''"> and sex_ like '%${sex}%' </if> </sql>
<!-- 根据用户名称和用户性别查询用户列表 --> <select id="findUserListResultMap" parameterType="queryVO" resultMap="userListResultMap"> select id id_,username username_,sex sex_ from users <!-- where自动将第一个and去掉 --> <where> <!-- 使用include引用 --> <include refid="query_user_where"/> </where> </select>
由于上边的UserMapper.xml中sql查询列和Users.java类属性不一致,需要定义resultMap:userListResultMap将sql查询列和Users.java类属性对应起来
<resultMap type="cn.ztt.pojo.Users" id="UserListResultMap"> <!-- id标签指定主键字段对应关系 column:列,数据库中的字段名称 property:属性,java中pojo中的属性名称 --> <id column="id_" property="id"/> <!-- result:标签指定非主键字段的对应关系 --> <result column="username_" property="username"/> <result column="sex_" property="sex"/> </resultMap>
1.2.2 mapper接口
public List<Users> findUserListResultMap() throws Exception;
2.关联查询
数据库模型:
2.1 一对一查询 (查询所有订单信息,关联查询下单用户信息)
2.1.1 方法一:使用resultType,定义订单信息po类,此po类中包括了订单信息和用户信息
(1)定义po类
public class OrdersCustom extends Orders{ private String username;// 用户名称 private String address;// 用户地址 setget... }
(2)Mapper.xml
<!-- 查询所有订单信息 --> <select id="findOrdersList" resultType="ordersCustom"> SELECT orders.*,user.username,user.address FROM orders, user WHERE orders.user_id = user.id </select>
(3)Mapper接口
public List<OrdersCustom> findOrdersList() throws Exception;
(4)测试
@Test public void TestFindOrdersList() throws Exception{ //获取session SqlSession session = sqlSessionFactory.openSession(); //获取mapper接口的代理对象 UserMapper userMapper = session.getMapper(UserMapper.class); List<OrdersCustom> list = userMapper.findOrdersList(); System.out.println(list); //关闭session session.close(); }
2.1.2 方法二:使用resultMap,定义专门的resultMap用于映射一对一查询结果
(1)定义po类
在Orders类中加入User属性,user属性中用于存储关联查询的用户信息,因为订单关联查询用户是一对一关系,所以这里使用单个User对象存储关联查询的用户信息。
public class Orders { private Integer id; private Integer userId; private String number; private Date createtime; private String note; private User user; setget... }
(2)Mapper.xml (使用association完成关联查询,将关联查询信息映射到pojo对象中)
<!-- 查询订单关联用户信息使用resultMap --> <resultMap type="cn.ztt.pojo.Orders" id="orderUserResultMap"> <id column="id" property="id"/> <result column="user_id" property="userId"/> <result column="number" property="number"/> <result column="createtime" property="createtime"/> <result column="note" property="note"/> <!-- 一对一关联映射--> <!-- property:Orders对象的user属性 javaType:user属性对应的类型 --> <associationproperty="user" javaType="cn.ztt.pojo.User"> <!-- column:user表的主键对应的列 property:user对象中id属性--> <id column="user_id" property="id"/> <result column="username" property="username"/> <result column="address" property="address"/> </association> </resultMap>
<select id="findOrdersWithUserResultMap" resultMap="orderUserResultMap"> SELECT o.id, o.user_id, o.number, o.createtime, o.note, u.username, u.address FROM orders o JOIN `user` u ON u.id = o.user_id </select>
(3)Mapper接口
public List<Orders> findOrdersWithUserResultMap() throws Exception;
(4)测试
@Test public void TestFindOrdersListResultMap() throws Exception{ //获取session SqlSession session = sqlSessionFactory.openSession(); //获取mapper接口的代理对象 UserMapper userMapper = session.getMapper(UserMapper.class); List<Orders> list = userMapper.findOrdersWithUserResultMap(); System.out.println(list); //关闭session session.close(); }
2.2 一对多查询 (查询所有用户信息及用户关联的订单信息)
使用resultMap实现如下:
(1)定义po类
在User类中加入List<Orders> orders属性
public class User { private int id; private String username;// 用户名 private String sex;// 性别 private Date birthday;// 生日 private String address;// 地址 private List<Orders> ordersList; setget... }
(2)Mapper.xml (使用collection完成关联查询,将关联查询信息映射到pojo对象中,collection部分定义了用户关联的订单信息)
<resultMap type="cn.ztt.pojo.User" id="userOrderResultMap"> <!-- 用户信息映射 --> <id property="id" column="id"/> <result property="username" column="username"/> <result property="birthday" column="birthday"/> <result property="sex" column="sex"/> <result property="address" column="address"/> <!-- 一对多关联映射 --> <collectionproperty="ordersList" ofType="cn.ztt.pojo.Orders"> <id property="id" column="oid"/> <!--用户id已经在user对象中存在,此处可以不设置--> <!-- <result property="userId" column="id"/> --> <result property="number" column="number"/> <result property="createtime" column="createtime"/> <result property="note" column="note"/> </collection> </resultMap> <select id="getUserOrderList" resultMap="userOrderResultMap"> SELECT u.*, o.id oid,o.number,o.createtime,o.note FROM `user` u LEFT JOIN orders o ON u.id = o.user_id </select>
(3)Mapper接口
public List<User> getUserOrderList() throws Exception;
(4)测试
@Test public void TestGetUserOrderList() throws Exception{ //获取session SqlSession session = sqlSessionFactory.openSession(); //获取mapper接口的代理对象 UserMapper userMapper = session.getMapper(UserMapper.class); List<User> list = userMapper.getUserOrderList(); System.out.println(list); //关闭session session.close(); }