返回顶部

Mybatis之旅第四篇-输入输出映射

一、引言

在日常开发用到mybatis时,因为实际的开发业务场景很复杂,不论是输入的查询条件,还是返回的结果,经常是需要根据业务来定制,这个时候我们就需要自己来定义一些输入和输出映射

二、parameterType(输入映射)

输入映射是在映射文件中通过parameterType指定输入参数的类型,类型可以是简单类型、hashmap、pojo的包装类型,当我们去查询用户时,有些字段基本不会用作查询条件,还有一些时候我们需要连表查询,那么这个时候我们可以用到包装类。

新建pojo包,定义包装类:

public class QueryVo {
    //pojo
    private User user;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
}

将UserMapper.xml文件移至com.yuanqinnan.mapper包中,并增加一个查询方法

<select id="queryByQo" parameterType="com.yuanqinnan.pojo.QueryVo" resultType="com.yuanqinnan.model.User">
    SELECT * from user  where username like '%${user.username}%'
</select>

UserMapper中增加接口:

List<User> queryByQo(QueryVo queryVo);

结构如图:

将SqlMapConfig.xml 中其他的配置恢复原先配置,引入mapper方式进行修改

<mappers>
    <package name="com.yuanqinnan.mapper"/>
</mappers>

测试方法:

@Test
public void testQueryUserByUsername2() {
    // 获取sqlSession,和spring整合后由spring管理
    SqlSession sqlSession = this.sqlSessionFactory.openSession();

    // 从sqlSession中获取Mapper接口的代理对象
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    // 执行查询方法
    QueryVo queryVo=new QueryVo();
    User user=new User();
    user.setUsername("张");
    queryVo.setUser(user);
    List<User> list = userMapper.queryByQo(queryVo);
    for (User user2 : list) {
        System.out.println(user2);
    }

    // 和spring整合后由spring管理
    sqlSession.close();
}

原以为会很顺利的出现结果,结果一直报错:invalid bound statement (not found),这个错误是找不到相应sql,可是明明路径和sql都是对的,最后竟然发现是需要在pom.xml文件中配置resource,不然mapper.xml文件就会被漏掉,这种错误真是太恼火了,pom加上配置:

<build>
  <resources>
    <resource>
      <directory>src/main/java</directory>
      <includes>
        <include>**/*.properties</include>
        <include>**/*.xml</include>
      </includes>
      <filtering>false</filtering>
    </resource>
  </resources>
</build>

得到测试结果:

输入映射比较简单,一般不会使用包装类,而是根据需要的条件去设置字段比较好

三、resultType(输出类型)

输出类型有简单类型,pojo类,pojo列表,pojol类和列表在前面的例子中都有演示,下面看一个简单类型的

新增方法:

<select id="queryUserCount" resultType="int">
    select count(*) from user
</select>

接口:

int queryUserCount();

测试:

@Test
public void testQueryUserCount() {
    // 获取sqlSession,和spring整合后由spring管理
    SqlSession sqlSession = this.sqlSessionFactory.openSession();

    // 从sqlSession中获取Mapper接口的代理对象
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    // 执行查询方法
    int count= userMapper.queryUserCount() ;
    System.out.println(count);

    // 和spring整合后由spring管理
    sqlSession.close();
}

结果:10

四、resultMap

resultType可以指定将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功。

如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系 ,resultMap实质上还需要将查询结果映射到pojo对象中。

resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo和list实现一对一查询和一对多查询。

下面通过例子来说明:

先新增一张订单表,sql如下:

DROP TABLE IF EXISTS `order`;
CREATE TABLE `order` (
  `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_order_1` (`user_id`),
  CONSTRAINT `FK_order_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of order
-- ----------------------------
INSERT INTO `order` VALUES ('3', '1', '1000010', '2015-02-04 13:22:35', null);
INSERT INTO `order` VALUES ('4', '1', '1000011', '2015-02-03 13:22:41', null);
INSERT INTO `order` VALUES ('5', '10', '1000012', '2015-02-12 16:13:23', null);

实体:

public class Order {

    // 订单id
    private int id;
    // 用户id
    private Integer userId;
    // 订单号
    private String number;
    // 订单创建时间
    private Date createtime;
    // 备注
    private String note;

    public int getId() {
        return id;
    }

    public Integer getUserId() {
        return userId;
    }

    public String getNumber() {
        return number;
    }

    public Date getCreatetime() {
        return createtime;
    }

    public String getNote() {
        return note;
    }

    public void setId(int id) {
        this.id = id;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public void setCreatetime(Date createtime) {
        this.createtime = createtime;
    }

    public void setNote(String note) {
        this.note = note;
    }
    @Override
    public String toString() {
        return "Order{" +
                "id=" + id +
                ", userId=" + userId +
                ", number='" + number + '\'' +
                ", createtime=" + createtime +
                ", note='" + note + '\'' +
                '}';
    }
}

新增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.yuanqinnan.mapper.OrderMapper">
    <!-- 查询所有的订单数据 -->
    <select id="queryOrderAll" resultType="com.yuanqinnan.model.Order">
      SELECT id, user_id,
      number,
      createtime, note FROM `order`
   </select>
</mapper>

新增OrderMapper接口

public interface OrderMapper {
    List<Order> queryOrderAll();
}

测试:

@Test
public void testQueryAll() {
    // 获取sqlSession
    SqlSession sqlSession = this.sqlSessionFactory.openSession();
    // 获取OrderMapper
    OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);

    // 执行查询
    List<Order> list = orderMapper.queryOrderAll();
    for (Order order : list) {
        System.out.println(order);
    }
}

结构如图:

 

结果:

发现userId为null,用resultMap解决,修改OrderMapper.xml,定义resultMap

<?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.yuanqinnan.mapper.OrderMapper">
    <!-- resultMap最终还是要将结果映射到pojo上,type就是指定映射到哪一个pojo -->
    <!-- id:设置ResultMap的id -->
    <resultMap type="com.yuanqinnan.model.Order" 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" />
    </resultMap>


    <!-- 查询所有的订单数据 -->
    <select id="queryOrderAll" resultType="com.yuanqinnan.model.Order">
      SELECT id, user_id,
      number,
      createtime, note FROM `order`
   </select>

    <select id="queryOrderAll2" resultMap="orderResultMap">
      SELECT id, user_id,
      number,
      createtime, note FROM `order`
   </select>
</mapper>

增加接口:

List<Order> queryOrderAll2();

测试方法:

@Test
public void testQueryAll2() {
    // 获取sqlSession
    SqlSession sqlSession = this.sqlSessionFactory.openSession();
    // 获取OrderMapper
    OrderMapper orderMapper = sqlSession.getMapper(OrderMapper.class);

    // 执行查询
    List<Order> list = orderMapper.queryOrderAll2();
    for (Order order : list) {
        System.out.println(order);
    }
}

结果:

posted @ 2019-03-24 17:15 茶底世界 阅读(...) 评论(...) 编辑 收藏