举例:由于一个订单信息只会是一我的下的订单,因此从查询订单信息出发,关联查询用户信息为一对一查询。若是从用户信息出发,查询用户下的订单信息则为一对多查询,由于一个用户能够下多个订单。java
查询全部订单信息,关联查询下单用户信息。mysql
主信息:订单表sql
从信息:用户表数据库
SELECT orders.*, user.username, user.address FROM orders LEFT JOIN user ON orders.user_id = user.id
返回resultType方式比较简单,也比较经常使用,就不作介绍了。session
使用resultMap进行结果映射,定义专门的resultMap用于映射一对一查询结果。mybatis
建立OrdersExt类(该类用于结果集封装),加入User属性,user属性中用于存储关联查询的用户信息,由于订单关联查询用户是一对一关系,因此这里使用单个User对象存储关联查询的用户信息。app
public class OrdersExt extends Orders { private User user;// 用户对象 // get/set。。。。 }
在UserMapper.xml中,添加如下代码:性能
<!-- 查询订单关联用户信息使用resultmap --> <resultMap type="OrdersExt" id="ordersAndUserRstMap"> <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属性对应 的类型 --> <association property="user" javaType="com.kkb.mybatis.po.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="findOrdersAndUserRstMap" resultMap="ordersAndUserRstMap"> 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>
在UserMapper接口中,添加如下接口方法:测试
public List<OrdersExt> findOrdersAndUserRstMap() throws Exception;
在UserMapperTest测试类中,添加测试代码:spa
public void testfindOrdersAndUserRstMap()throws Exception{ //获取session SqlSession session = sqlSessionFactory.openSession(); //获限mapper接口实例 UserMapper userMapper = session.getMapper(UserMapper.class); //查询订单信息 List<OrdersExt> list = userMapper.findOrdersAndUserRstMap(); System.out.println(list); //关闭session session.close(); }
使用resultMap进行结果映射时,具体是使用association完成关联查询的映射,将关联查询信息映射到pojo对象中。
查询全部用户信息及用户关联的订单信息。
主信息:用户信息
从信息:订单信息
SELECT u.*, o.id oid, o.number, o.createtime, o.note FROM `user` u LEFT JOIN orders o ON u.id = o.user_id
在一对多关联查询时,只能使用resultMap进行结果映射:
一、一对多关联查询时,sql查询结果有多条,而映射对象是一个。
二、resultType完成结果映射的方式的一条记录映射一个对象。
三、resultMap完成结果映射的方式是以[主信息]为主对象,[从信息]映射为集合或者对象,而后封装到主对象中。
在User类中加入List<Orders> orders属性。
在UserMapper.xml文件中,添加如下代码:
<resultMap type="user" id="userAndOrderRstMap"> <!-- 用户信息映射 --> <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"/> <!-- 一对多关联映射 --> <collection property="orders" ofType="orders"> <id property="id" column="oid"/> <result property="userId" column="id"/> <result property="number" column="number"/> <result property="createtime" column="createtime"/> <result property="note" column="note"/> </collection> </resultMap> <select id="findUserAndOrderRstMap" resultMap="userAndOrderRstMap"> 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>
Collection标签:定义了一对多关联的结果映射。
// resultMap入门 public List<User> findUserAndOrdersRstMap() throws Exception;
@Test public void testFindUserAndOrdersRstMap() { SqlSession session = sqlSessionFactory.openSession(); UserMapper userMapper = session.getMapper(UserMapper.class); List<User> result = userMapper.findUserAndOrdersRstMap(); for (User user : result) { System.out.println(user); } session.close(); }
MyBatis根据对关联对象查询的select语句的执行时机,分为三种类型:直接加载、侵入式加载与深度延迟加载
延迟加载策略须要在Mybatis的全局配置文件中,经过<settings>标签进行设置。
查询订单信息及它的下单用户信息。
经过对全局参数:lazyLoadingEnabled进行设置,默认就是false。
<settings> <!-- 延迟加载总开关 --> <setting name="lazyLoadingEnabled" value="false"/> </settings>
<settings> <!-- 延迟加载总开关 --> <setting name="lazyLoadingEnabled" value="true"/> <!-- 侵入式延迟加载开关 --> <setting name="aggressiveLazyLoading" value="true"/> </settings>
<settings> <!-- 延迟加载总开关 --> <setting name="lazyLoadingEnabled" value="true"/> <!-- 侵入式延迟加载开关 --> <setting name="aggressiveLazyLoading" value="false"/> </settings>
动态SQL的思想:就是使用不一样的动态SQL标签去完成字符串的拼接处理、循环判断。
解决的问题是:
综合查询的案例中,查询条件是由页面传入,页面中的查询条件可能输入用户名称,也可能不输入用户名称。
<select id="findUserList" parameterType="queryVo" resultType="user"> SELECT * FROM user where 1=1 <if test="user != null"> <if test="user.username != null and user.username != ''"> AND username like '%${user.username}%' </if> </if> </select>
注意:要作『不等于空』字符串校验。
上边的sql中的1=1,虽然能够保证sql语句的完整性:可是存在性能问题。Mybatis提供where标签解决该问题。
代码修改以下:
<select id="findUserList" parameterType="queryVo" resultType="user"> SELECT * FROM user <!-- where标签会处理它后面的第一个and --> <where> <if test="user != null"> <if test="user.username != null and user.username != ''"> AND username like '%${user.username}%' </if> </if> </where> </select>
在映射文件中可以使用sql标签将重复的sql提取出来,而后使用include标签引用便可,最终达到sql重用的目的,具体实现以下:
原映射文件中的代码:
<select id="findUserList" parameterType="queryVo" resultType="user"> SELECT * FROM user <!-- where标签会处理它后面的第一个and --> <where> <if test="user != null"> <if test="user.username != null and user.username != ''"> AND username like '%${user.username}%' </if> </if> </where> </select>
<sql id="query_user_where"> <if test="user != null"> <if test="user.username != null and user.username != ''"> AND username like '%${user.username}%' </if> </if> </sql>
<!-- 使用包装类型查询用户 使用ognl从对象中取属性值,若是是包装对象可使用.操做符来取内容部的属性 --> <select id="findUserList" parameterType="queryVo" resultType="user"> SELECT * FROM user <!-- where标签会处理它后面的第一个and --> <where> <include refid="query_user_where"></include> </where> </select>
注意:
一、若是引用其它mapper.xml的sql片断,则在引用时须要加上namespace,以下:
<include refid="namespace.sql片断”/>
综合查询时,传入多个id查询用户信息,用下边两个sql实现:
SELECT * FROM USER WHERE username LIKE '%老郭%' AND (id =1 OR id =10 OR id=16) SELECT * FROM USER WHERE username LIKE '%老郭%' AND id IN (1,10,16)
在pojo中定义list属性ids存储多个用户id,并添加getter/setter方法
<sql id="query_user_where"> <if test="user != null"> <if test="user.username != null and user.username != ''"> AND username like '%${user.username}%' </if> </if> <if test="ids != null and ids.size() > 0"> <!-- collection:指定输入的集合参数的参数名称 --> <!-- item:声明集合参数中的元素变量名 --> <!-- open:集合遍历时,须要拼接到遍历sql语句的前面 --> <!-- close:集合遍历时,须要拼接到遍历sql语句的后面 --> <!-- separator:集合遍历时,须要拼接到遍历sql语句之间的分隔符号 --> <foreach collection="ids" item="id" open=" AND id IN ( " close=" ) " separator=","> #{id} </foreach> </if> </sql>
在UserMapperTest测试代码中,修改testFindUserList方法,以下:
@Test public void testFindUserList() throws Exception { SqlSession sqlSession = sqlSessionFactory.openSession(); // 得到mapper的代理对象 UserMapper userMapper = sqlSession.getMapper(UserMapper.class); // 建立QueryVo对象 QueryVo queryVo = new QueryVo(); // 建立user对象 User user = new User(); user.setUsername("老郭"); queryVo.setUser(user); List<Integer> ids = new ArrayList<Integer>(); ids.add(1);// 查询id为1的用户 ids.add(10); // 查询id为10的用户 queryVo.setIds(ids); // 根据queryvo查询用户 List<User> list = userMapper.findUserList(queryVo); System.out.println(list); sqlSession.close(); }
若是parameterType不是POJO类型,而是List或者Array的话,那么foreach语句中,collection属性值须要固定写死为list或者array。