复杂结果集映射

MyBatis 的 ResultMap 可以进行复杂的关联关系映射:

  • 映射管理关系
  • 集合映射
    • 数据量太大时候,小心内存泄漏出问题
    • 替换为分页查询
      1.引子
      在一个在线评论系统中,用户可以发帖,其他用户可以评论和转发,其实体关系如图:
      这里写图片描述
      创建SQL初始化脚本
create table blog_user(
  u_id varchar(100),
  u_name varchar(100),
  u_password varchar(100),
  PRIMARY KEY (u_id)
);

create table blog_post(
   p_id  varchar(100),
   p_body varchar(1000),
   p_user_id varchar(100),
   PRIMARY KEY (p_id)
);

create table blog_comment(
   c_id  varchar(100),
   c_body varchar(1000),
   c_post_id varchar(100),
   PRIMARY KEY (c_id)
);


create table blog_forward(
   f_id  varchar(100),
   f_body varchar(1000),
   f_post_id varchar(100),
   PRIMARY KEY (f_id)
);

初始化数据:

insert into blog_user
    (u_id, u_name, u_password)
values
    ('1', 'Tom', '123');

insert into blog_user 
    (u_id, u_name, u_password)
values
    ('2', 'Jerry', '123');

insert into blog_post 
    (p_id, p_body, p_user_id)
values
    ('1','今天天气不错!', '1');

insert into blog_post 
    (p_id, p_body, p_user_id)
values
    ('2','今天你吃了吗!', '1');


insert into blog_comment 
    (c_id, c_body, c_post_id)
values
    (1,'雾霾太重', 1);

insert into blog_comment 
    (c_id, c_body, c_post_id)
values
    (2,'是作为天气好', 1);

insert into blog_comment 
    (c_id, c_body, c_post_id)
values
    (3,'做梦', 1);

以上数据表示:一个人发了一个帖子,有3个用户进行了回复。
2.创建映射实体
实体类:

public class User implements Serializable {
    private static final long serialVersionUID = 2198506197294786297L;
    private String id;
    private String name;
    private String password;

    public User() {
    }

    public User(String id, String name, String password) {
        super();
        this.id = id;
        this.name = name;
        this.password = password;
    }

    public String getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((id == null) ? 0 : id.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        User other = (User) obj;
        if (id == null) {
            if (other.id != null)
                return false;
        } else if (!id.equals(other.id))
            return false;
        return true;
    }

    @Override
    public String toString() {
        return "User [id=" + id + ", name=" + name + ", password=" + password + "]";
    }


}

public class Comment implements Serializable{
    private static final long serialVersionUID = 6832982316145348127L;
    private String id;
    private String body;

    public Comment() {
    }

    public String getId() {
        return id;
    }

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

    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((id == null) ? 0 : id.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Comment other = (Comment) obj;
        if (id == null) {
            if (other.id != null)
                return false;
        } else if (!id.equals(other.id))
            return false;
        return true;
    }

    @Override
    public String toString() {
        return "Comment [id=" + id + ", body=" + body + "]";
    }


}


public class Post implements Serializable{
    private static final long serialVersionUID = -4123583063151215606L;
    private String id;
    private String body;
    //发帖人
    private User user;

    //帖子的回复
    private List<Comment> comments = 
            new ArrayList<Comment>();

    public Post() {
    }

    public Post(String id, String body, User user) {
        super();
        this.id = id;
        this.body = body;
        this.user = user;
    }

    public String getId() {
        return id;
    }

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

    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }

    public User getUser() {
        return user;
    }

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

    public List<Comment> getComments() {
        return comments;
    }

    public void setComments(List<Comment> comments) {
        this.comments = comments;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((id == null) ? 0 : id.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Post other = (Post) obj;
        if (id == null) {
            if (other.id != null)
                return false;
        } else if (!id.equals(other.id))
            return false;
        return true;
    }

    @Override
    public String toString() {
        return "Post [id=" + id + ", body=" + body + ", user=" + user + ", comments=" + comments + "]";
    }

}
  1. 创建映射接口
public interface PostDao {
    Post findPostById(String id);
}
  1. 为Mapper.xml
<?xml version="1.0" encoding="UTF-8" ?>  
<!DOCTYPE mapper PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN"      
 "http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd">
<mapper namespace="cn.tedu.blog.dao.PostDao">
    <!-- 自定义映射规则 -->
    <resultMap id="postResultMap"
        type="cn.tedu.blog.entity.Post">
        <result property="id" column="p_id"/>
        <result property="body" column="body"/>
        <!-- association 关联,用于映射外键 -->
        <association property="user"
            column="p_user_id" 
            javaType="cn.tedu.blog.entity.User">
            <id property="id" column="u_id"/>
            <result property="name" 
                column="name"/>
            <result property="password"
                column="password"/>
        </association>
        <!-- 集合映射 -->
        <collection property="comments"
            javaType="java.util.ArrayList"
            ofType="cn.tedu.blog.entity.Comment"
            column="p_id"
            select="selectComment">
        </collection>
    </resultMap>

    <select id="selectComment" 
        resultType="cn.tedu.blog.entity.Comment">
        select 
            c_id as id,
            c_body as body
        from 
            blog_comment
        where 
            c_post_id=#{p_id} 
    </select>

    <select id="findPostById"
        parameterType="string"
        resultMap="postResultMap">
        select 
            p.p_id ,
            p.p_body as body,
            p.p_user_id,
            u.u_id,
            u.u_name as name,
            u.u_password as password
        from 
            blog_post p
            left outer join blog_user u 
                on p.p_user_id=u.u_id
        where 
            p_id=#{id}  
    </select>
</mapper>

**其中:
利用resultMap处理复杂映射
collection用于映射集合
assocition用于关联映射**
4.配置Spring
配置spring-mybatis.xml文件:

<bean id="mapperScanner2"
    class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <!-- 扫描cn.tedu.note.dao中的mapper接口 -->
    <property name="basePackage" 
        value="cn.tedu.blog.dao" />
</bean>

5.测试

@Test
public void testFindPostById(){
    PostDao dao = ctx.getBean(
        "postDao",PostDao.class);
    Post post = dao.findPostById("1");
    System.out.println(post); 
}
MyBatis支持通过结果映射来解决复杂SQL查询结果的映射问题。如果查询结果是多表联合查询的情况,需要进行结果映射,可以使用MyBatis提供的嵌套查询或者嵌套结果映射。 下面以两个表的联合查询为例,介绍MyBatis如何进行结果映射: 首先,我们假设有两个表:user和order。 user表的结构如下: ``` CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) NOT NULL, `age` int(11) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; ``` order表的结构如下: ``` CREATE TABLE `order` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user_id` int(11) NOT NULL, `order_no` varchar(50) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; ``` 其中,order表的user_id字段与user表的id字段相关联。 接下来,我们需要进行两个表的联合查询,并将查询结果映射到一个Java对象中。Java对象的结构如下: ``` public class UserOrder { private int id; private String name; private int age; private List<Order> orders; // getter、setter方法 } ``` UserOrder对象包含了user表和order表的字段信息,并且使用List类型的orders属性来保存order表的相关信息。 在MyBatis的Mapper文件中,我们可以使用嵌套查询来实现两个表的联合查询,并将查询结果映射到UserOrder对象中,具体实现如下: ``` <select id="getUserOrder" resultMap="userOrderMap"> SELECT u.id, u.name, u.age, o.id as order_id, o.order_no FROM user u LEFT JOIN order o ON u.id = o.user_id WHERE u.id = #{id} </select> <resultMap id="userOrderMap" type="UserOrder"> <id column="id" property="id"/> <result column="name" property="name"/> <result column="age" property="age"/> <collection property="orders" ofType="Order"> <id column="order_id" property="id"/> <result column="order_no" property="orderNo"/> </collection> </resultMap> ``` 在getUserOrder查询语句中,我们使用了LEFT JOIN关键字来进行两个表的联合查询,并使用了WHERE子句来指定查询条件。在resultMap中,我们使用了collection标签来映射orders属性,并使用了ofType属性来指定orders合元素的类型为Order对象。 需要注意的是,在resultMap中使用collection标签来映射orders属性时,需要使用id标签来映射order表的主键,使用result标签来映射order表的其他字段信息。 最后,我们通过调用session.selectOne方法来执行getUserOrder查询语句,并将查询结果映射到UserOrder对象中: ``` UserOrder userOrder = session.selectOne("getUserOrder", 1); ``` 以上就是在MyBatis中进行复杂结果映射的方法。通过使用嵌套查询或嵌套结果映射,可以轻松地实现多表联合查询,并将查询结果映射到Java对象中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值