Mybatis之输入输出映射

参考自《mybatis parametertype 多个参数》
参考自《mybatis学习笔记(7)-输出映射》

输入映射

一、单个参数

方案1

public List<XXBean> getXXBeanList(@param("id")String id);  

<select id="getXXXBeanList" parameterType="java.lang.String" resultType="XXBean">

  select t.* from tableName t where t.id= #{id}  

</select>  

其中方法名和ID一致,#{}中的参数名与方法中的参数名一致, 这里采用的是@Param这个参数,实际上@Param这个最后会被Mabatis封装为map类型的。

select 后的字段列表要和bean中的属性名一致, 如果不一致的可以用 as 来补充。

方案2

//在实际需求中,我们经常需要结合多个条件综合查询,而这些条件并不在同一个POJO类中,
//所以需要对POJO类进行包装,生成另外一个类作为参数类型
public class UserQueryVO {
    // 用户信息
    private User user;
    // 订单信息
    private Order order;
    //...
}

public List<User> getUserList(UserQueryVO vo);

<!--使用包装POJO类作为参数,查询用户列表 -->
<select id="getUserList" parameterType="com.zyj.mybatis.po.UserQueryVO" resultType="com.zyj.mybatis.po.User">
    select * from user where username like '%${user.username}%' and sex = #{user.sex}
</select>

二、多个参数

方案1

public List<XXXBean> getXXXBeanList(String xxId, String xxCode);  

<select id="getXXXBeanList" resultType="XXBean">不需要写parameterType参数

  select t.* from tableName where id = #{0} and name = #{1}  

</select>  

由于是多参数那么就不能使用parameterType, 改用#{index}是第几个就用第几个的索引,索引从0开始

方案2

public List<XXXBean> getXXXBeanList(@Param("id")String id, @Param("code")String code);  

<select id="getXXXBeanList" resultType="XXBean">

  select t.* from tableName where id = #{id} and name = #{code}  

</select>  

由于是多参数那么就不能使用parameterType, 这里用@Param来指定哪一个

三、Map封装多参数:

public List<XXXBean> getXXXBeanList(HashMap map);  

<select id="getXXXBeanList" parameterType="hashmap" resultType="XXBean">

  select 字段... from XXX where id=#{xxId} code = #{xxCode}  

</select>

其中hashmap是mybatis自己配置好的直接使用就行。map中key的名字是那个就在#{}使用那个

四、List封装in:

public List<XXXBean> getXXXBeanList(List<String> list);  

<select id="getXXXBeanList" parameterType="list" resultType="XXBean">
  select 字段... from XXX where id in
  <foreach item="item" index="index" collection="list" open="(" separator="," close=")">  
    #{item}  
  </foreach>  
</select>  

foreach 最后的效果是select 字段... from XXX where id in ('1','2','3','4') 

注意:如果parameterType是List或者Array的话,那么foreach语句中,collection属性值需要固定为list或者array。

五、selectList()只能传递一个参数,但实际所需参数既要包含String类型,又要包含List类型时的处理方法:

将参数放入Map,再取出Map中的List遍历。如下:

List<String> list_3 = new ArrayList<String>();
Map<String, Object> map2 = new HashMap<String, Object>();

list.add("1");
list.add("2");
map.put("list", list);  //网址id
map.put("siteTag", "0");//网址类型

public List<SysWeb> getSysInfo(Map<String, Object> map2) {
    return getSqlSession().selectList("sysweb.getSysInfo", map2);
}

<select id="getSysInfo" parameterType="java.util.Map" resultType="SysWeb">
    select t.sysSiteId, t.siteName, t1.mzNum as siteTagNum, t1.mzName as siteTag, t.url, t.iconPath
    from TD_WEB_SYSSITE t
    left join TD_MZ_MZDY t1 on t1.mzNum = t.siteTag and t1.mzType = 10
    WHERE t.siteTag = #{siteTag } 
    and t.sysSiteId not in 
    <foreach collection="list" item="item" index="index" open="(" close=")" separator=",">
        #{item}
    </foreach>
</select>

输出映射基础之单表查询

输出映射有两种方式

 1. resultType
 2. resultMap

resultType

1.使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。
2.如果查询出来的列名和pojo中的属性名全部不一致,没有创建pojo对象。
3.只要查询出来的列名和pojo中的属性有一个一致,就会创建pojo对象。

输出简单类型

mapper.xml

<!-- 用户信息综合查询总数
    parameterType:指定输入类型和findUserList一样
    resultType:输出结果类型
-->
<select id="findUserCount" parameterType="com.iot.mybatis.po.UserQueryVo" resultType="int">
    SELECT count(*) FROM user WHERE user.sex=#{userCustom.sex} AND user.username LIKE '%${userCustom.username}%'
</select>

mapper.java

//用户信息综合查询总数
@Test
public void testFindUserCount() throws Exception {
    //......
    //创建UserMapper对象,mybatis自动生成mapper代理对象
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

    //创建包装对象,设置查询条件
    UserQueryVo userQueryVo = new UserQueryVo();
    UserCustom userCustom = new UserCustom();
    userCustom.setSex("1");
    userCustom.setUsername("小");
    userQueryVo.setUserCustom(userCustom);

    //调用userMapper的方法
    int count = userMapper.findUserCount(userQueryVo);
    //......
}

小结
查询出来的结果集只有一行且一列,可以使用简单类型进行输出映射。

输出pojo对象和pojo列表

不管是输出的pojo单个对象还是一个列表(list中包括pojo),在mapper.xml中resultType指定的类型是一样的。

在mapper.java指定的方法返回值类型不一样:

输出单个pojo对象,方法返回值是单个对象类型

//根据id查询用户信息
public User findUserById(int id) throws Exception;

输出pojo对象list,方法返回值是List

//根据用户名列查询用户列表
public List<User> findUserByName(String name) throws Exception;

生成的动态代理对象中是根据mapper方法的返回值类型确定是调用selectOne(返回单个对象调用)还是selectList (返回集合对象调用 ).

resultMap

mybatis中使用resultMap完成高级输出结果映射。(一对多,多对多)

resultMap使用方法
如果查询出来的列名和pojo的属性名不一致,则需要通过定义一个resultMap对列名和pojo属性名之间作一个映射关系。

1.定义resultMap

2.使用resultMap作为statement的输出映射类型

定义reusltMap

<!-- 定义resultMap
将SELECT id id_,username username_ FROM USER 和User类中的属性作一个映射关系

type:resultMap最终映射的java对象类型,可以使用别名
id:对resultMap的唯一标识
-->
<resultMap type="user" id="userResultMap">
   <!-- id表示查询结果集中唯一标识 
   column:查询出来的列名
   property:type指定的pojo类型中的属性名
   最终resultMap对column和property作一个映射关系 (对应关系)
   -->
   <id column="id_" property="id"/>
   <!-- 
   result:对普通名映射定义
   column:查询出来的列名
   property:type指定的pojo类型中的属性名
   最终resultMap对column和property作一个映射关系 (对应关系)
    -->
   <result column="username_" property="username"/>

</resultMap>

使用resultMap作为statement的输出映射类型

<!-- 使用resultMap进行输出映射
    resultMap:指定定义的resultMap的id,如果这个resultMap在其它的mapper文件,前边需要加namespace
-->
<select id="findUserByIdResultMap" parameterType="int" resultMap="userResultMap">
    SELECT id id_,username username_ FROM USER WHERE id=#{value}
</select>

mapper.java

//根据id查询用户信息,使用resultMap输出
public User findUserByIdResultMap(int id) throws Exception;

测试代码

@Test
public void testFindUserByIdResultMap() throws Exception {
    //......
    //创建UserMapper对象,mybatis自动生成mapper代理对象
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

    //调用userMapper的方法
    User user = userMapper.findUserByIdResultMap(1);
    //.......
}

小结
使用resultType进行输出映射,只有查询出来的列名和pojo中的属性名一致,该列才可以映射成功。
如果查询出来的列名和pojo的属性名不一致,通过定义一个resultMap对列名和pojo属性名之间作一个映射关系。


输出映射进阶之关联查询

场景:一个订单对应一个用户,同时一个订单对应多个订单明细

数据库

这里写图片描述

一对一(订单为主)

需求:查询订单列表,关联查询用户信息
sql语句:

SELECT orders.*, user.`username`, user.`sex` FROM orders, USER WHERE orders.`user_id` = user.`id`

方式一:resultType

由于订单pojo类orders中没有含有用户表user字段,所以这里可以包装订单类orders

public class OrdersExt extends Orders {
    private String username;
    private String sex;
    //省略getter和setter方法
}
// mapper接口
public interface OrdersMapper {
    public List<OrdersExt> findOrdersAndUserByRstType();
}

// mapper映射文件
<mapper namespace="com.zyj.mybatis.mapper.OrdersMapper">
    <select id="findOrdersAndUserByRstType" resultType="com.zyj.mybatis.dto.OrdersExt">

        SELECT orders.*, user.`username`, user.`sex` FROM orders, USER WHERE orders.`user_id` = user.`id`

    </select>
</mapper>

// 测试代码
@Test
public void testFindOrdersAndUserByRstType() {
    //......
    List<OrdersExt> list = ordersMapper.findOrdersAndUserByRstType();
    //......
}

小结:
1、一对一关联查询时,可以定义专门的扩展po类作为输出结果类型。
2、该扩展po类中定义了sql查询结果集所有的字段对应的属性。
3、此方法较为简单,企业中使用普遍。

方式二:resultMap

与方式一类似,扩展pojo类,与用户类User产生关联关系,并修改mapper映射文件

public class OrdersExt extends Orders {
    private User user;
    //省略getter和setter方法
}
// mapper接口
public interface OrdersMapper {
    public List<OrdersExt> findOrdersAndUserByRstMap();
}

// mapper映射文件
<resultMap type="com.zyj.mybatis.dto.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"/>

    <!-- 用户信息(一对一) -->
    <!-- association:一对一关联映射 -->
    <!-- property:关联信息查询的结果将要映射的扩展类中的对象属性名称 -->
    <!-- id标签:建议在关联查询时必须写上,不写不会报错,但是会影响性能 -->
    <association property="user" javaType="com.zyj.mybatis.po.User">
        <id column="user_id" property="id"/>
        <result column="username" property="username"/>
        <result column="sex" property="sex"/>
    </association>

</resultMap>

<select id="findOrdersAndUserByRstMap" resultMap="OrdersAndUserRstMap">
    SELECT 
      orders.*,
      user.`username`,
      user.`sex` 
    FROM
      orders,
      USER 
    WHERE orders.`user_id` = user.`id` 
</select>

// 测试代码
@Test
public void testFindOrdersAndUserByRstType() {
    //......
    List<OrdersExt> list = mapper.findOrdersAndUserByRstMap();
    //......
}

小结:
使用resultMap进行结果映射时,具体是使用association完成关联查询的映射,将关联查询信息映射到pojo对象中。

一对多(订单为主)

需求:查询订单列表,关联查询用户信息,而且同时附带相应的订单明细

sql语句:

SELECT 
  orders.id,
  orders.`number`,
  orders.`createtime`,
  user.`username`,
  user.`sex`,
  orderdetail.`id` detailId,
  orderdetail.`items_num` 
FROM
  orders,
  USER,
  orderdetail 
WHERE orders.`user_id` = user.`id` 
  AND orders.`id` = orderdetail.`orders_id` 

resultMap

public class OrdersExt extends Orders {
    private User user;
    private List<Orderdetail> details;
    //省略getter和setter方法
}
// mapper接口
public interface OrdersMapper {
    public List<OrdersExt> findOrdersAndDetailByRstMap();
}

// mapper映射文件
<!-- 这里extends继承了上面一对一的resultMap,对OdersExt关联的用户类User进行结果映射 -->
<!-- extends:可以继承一个已有的resultMap,指定resultMap的唯一标示即可 -->
<!-- 注意:继承时,只能继承type类型是一样的resultMap -->
<resultMap type="com.zyj.mybatis.dto.OrdersExt" id="OrdersAndDetailRstMap" extends="OrdersAndUserRstMap">
    <!-- 订单明细信息(一对多) -->
    <!-- collection:映射一对多关系 -->
    <collection property="details" ofType="com.zyj.mybatis.po.Orderdetail">
        <id column="detailId" property="id"/>
        <result column="items_num" property="itemsNum"/>
    </collection>
</resultMap>

<select id="findOrdersAndDetailByRstMap" resultMap="OrdersAndDetailRstMap">
    SELECT 
      orders.id,
      orders.`number`,
      orders.`createtime`,
      user.`username`,
      user.`sex`,
      orderdetail.`id` detailId,
      orderdetail.`items_num` 
    FROM
      orders,
      USER,
      orderdetail 
    WHERE orders.`user_id` = user.`id` 
      AND orders.`id` = orderdetail.`orders_id` 
</select>

// 测试代码
@Test
public void testFindOrdersAndUserByRstType() {
    //......
    List<OrdersExt> list = mapper.findOrdersAndDetailByRstMap();
    //......
}

多对多(用户为主)

需求:查询用户信息,关联查询该用户购买的商品信息
关系:一个用户对多个订单,一个订单对多个明细,一个明细对一个商品信息

sql语句:

SELECT 
  orders.id orders_id,
  orders.`number`,
  orders.`createtime`,
  user.`id` user_id,
  user.`username`,
  user.`sex`,
  orderdetail.`id` detail_id,
  orderdetail.`items_num`,
  items.`id` items_id,
  items.`name`,
  items.`price`
FROM
  orders,
  USER,
  orderdetail,
  items
WHERE orders.`user_id` = user.`id` 
AND orders.`id` = orderdetail.`orders_id`
AND orderdetail.`items_id` = items.`id`

修改pojo类

public class User {
    //一个用户对多个订单
    private List<Orders> orders;
    //...
}
public class Orders {
    // 一个订单对多个明细
    private List<Orderdetail> detail;
    //...
}
public class Orderdetail { 
    //一条明细对一条商品信息
    private Items items;
} 

mapper接口

public interface UserMapper {
    public List<User> findUserAndDetailByRstMap();
}

mapper映射文件

<!-- 多对多 -->
<resultMap type="com.zyj.mybatis.po.User" id="UserAndDetailRstMap">
    <!-- 用户信息  -->
    <id column="user_id" property="id"/>
    <result column="username" property="username"/>
    <result column="sex" property="sex"/>
    <!-- 一个用户对多个订单 -->  
    <collection property="orders" ofType="com.zyj.mybatis.po.Orders">
        <!-- 订单信息  -->
        <id column="orders_id" property="id"/>
        <result column="number" property="number"/>
        <result column="createtime" property="createtime"/>
        <!-- 一个订单对多个明细 -->
        <collection property="detail" ofType="com.zyj.mybatis.po.Orderdetail">
            <!-- 明细信息  -->
            <id column="detail_id" property="id"/>
            <result column="items_num" property="itemsNum"/>
            <!-- 一条明细对一条商品信息 -->
            <association property="items" javaType="com.zyj.mybatis.po.Items">
                <!-- 商品信息  -->
                <id column="items_id" property="id"/>
                <result column="name" property="name"/>
                <result column="price" property="price"/>
            </association>
        </collection>
    </collection>
</resultMap>

<select id="findUserAndDetailByRstMap" resultMap="UserAndDetailRstMap">
    SELECT 
      orders.id orders_id,
      orders.`number`,
      orders.`createtime`,
      user.`id` user_id,
      user.`username`,
      user.`sex`,
      orderdetail.`id` detail_id,
      orderdetail.`items_num`,
      items.`id` items_id,
      items.`name`,
      items.`price`
    FROM
      orders,
      USER,
      orderdetail,
      items
    WHERE orders.`user_id` = user.`id` 
    AND orders.`id` = orderdetail.`orders_id`
    AND orderdetail.`items_id` = items.`id`
</select>

测试代码

@Test
public void testFindUserAndDetailByRstMap() {
    //......
    List<User> list = mapper.findUserAndDetailByRstMap();
    //......
}

小结:
虽然resultMap和resultType都可以进行结果映射,但是使用resultType更加便捷,企业中建议使用resultType完成结果映射。
resultMap只有特殊场景才会用,比如延迟加载。

猜你喜欢

转载自blog.csdn.net/code_shadow/article/details/80574980