zoukankan      html  css  js  c++  java
  • 云笔记项目-MyBatis关联映射查询

    在云笔记学习过程中,又简单的介绍了MyBatis关联映射查询,以发帖作为例子,开始了对它的学习,不过本文只是查询,不涉及其他类型的数据库操作。由于查询帖子不是简单查询,简单的一一映射将不能满足需求,因此涉及到了复杂查询,需要使用关联查询来解决问题,以下将从数据库结构,配置文件等进行简单说明。

    数据库结构

    需要建立三张表,P_PERSON,P_POST,P_COMMENT,其中P_PERSON用于保存发帖人的基本信息,P_POST保存发帖内容,并且字段person_id作为外键关联P_PERSON的主键id,最后P_COMMENT用于保存回帖内容,其中字段post_id作为外键关联P_POST的主键id。以下是在Navicat中,三张表的关系图。

    建表&数据插入准备

    使用Eclipse在云笔记数据库中建立了以上三张表,以下是具体代码:

    (1)建立P_PERSON

    1 --MyBatis数据自增,MySQL中使用AUTO_INCREMENT,ORACLE中使用SEQUENCE
    2 CREATE TABLE P_PERSON(
    3       id int not null AUTO_INCREMENT,
    4       name VARCHAR(100),
    5       PRIMARY KEY(id)
    6 );

    (2)建立P_POST

    1 --为了学习MyBatis关系映射,再建立P_POST表和P_COMMENT表,其中P_POST表保存用户发的帖子,P_COMMENT表保存用户回复的帖子
    2 CREATE TABLE P_POST(
    3      id int not null AUTO_INCREMENT,
    4      title VARCHAR(100),
    5      person_id int,
    6      PRIMARY KEY(id)     
    7 );

    (3)建立P_COMMENT

    1 CREATE TABLE P_COMMENT(
    2     id int not null AUTO_INCREMENT,
    3     title VARCHAR(100),
    4     post_id int,
    5     PRIMARY KEY(id)
    6 );

    (4)建表完成后创建约束,关联表

    --使用P_POST的person_id作为外键,关联P_PERSON的主键id,将两张表关联起来
    ALTER TABLE P_POST ADD CONSTRAINT FK_ID FOREIGN KEY(person_id) REFERENCES P_PERSON(id); 
    
    --类似的,关联P_POST和P_COMMENT
    ALTER TABLE P_COMMENT ADD CONSTRAINT FK_ID_COMMENT FOREIGN KEY(post_id) REFERENCES P_POST(id);

    创建数据表对应实体类+DAO接口

    需要建立三个实体类,用于保存数据表对应信息,其中POST实体类不仅仅跟表信息一一对应,还包含person和comments属性,因此需要用到MyBatis关联映射查询。

    Person类,对应P_PERSON

    package com.boe.Entity;
    
    import java.io.Serializable;
    
    /**
     * 验证MyBatis返回自增类型,数据表对应实体类
    */ public class Person implements Serializable{ private static final long serialVersionUID = 4185328190674358099L; Integer id; //使用包装类,因为数据库中id有null的可能,包装类也可以为null,两者可以一一对应,如果使用基本数据类型将无法表示null String name; //如果查询的结果不完整,使用此构造方法初始化 public Person() { super(); }
    public Person(Integer id, String name) { super(); this.id = id; this.name = name; } @Override public String toString() { return "Person [id=" + id + ", name=" + name + "]"; } ...省略Get Set方法 }

    Post实体类,对应表P_POST

    package com.boe.Entity;
    
    import java.io.Serializable;
    import java.util.ArrayList;
    import java.util.List;
    
    public class Post implements Serializable{
        
        private static final long serialVersionUID = -2929218418809381846L;
        Integer id;
        String title;//帖子内容
        
        //添加人和评论
        Person person;
        List<Comment> comments=new ArrayList<Comment>();//实体内部有集合属性,集合最好初始化,防止空指针异常
        
        
        @Override
        public String toString() {
            return "Post [id=" + id + ", title=" + title + ", person=" + person + ", comments=" + comments + "]";
        }
        
        //如果查询不到person和comment,就调用此构造方法
        public Post() {
            super();
        }
    
    
        public Post(Integer id, String title, Person person, List<Comment> comments) {
            super();
            this.id = id;
            this.title = title;
            this.person = person;
            this.comments = comments;
        }
    
    ...省略Get Set方法
        
    }

    实体类Comment对应数据表P_COMMENT

    package com.boe.Entity;
    
    import java.io.Serializable;
    
    public class Comment implements Serializable{
        
        private static final long serialVersionUID = -3407225418917489641L;
        Integer id;
        String title;//评论内容
        Integer post_id;
        
        public Comment(Integer id, String title, Integer post_id) {
            super();
            this.id = id;
            this.title = title;
            this.post_id = post_id;
        }
    
    
        @Override
        public String toString() {
            return "Comment [id=" + id + ", title=" + title + ", post_id=" + post_id + "]";
        }
            
    ...省略Get Set方法    
    
    }

    DAO接口的话,需要建立一个方法,根据id来查找帖子,帖子内容包含帖子id,帖子内容title,发帖人person和评论内容comments。

     1 package com.boe.Dao;
     2 
     3 import org.springframework.stereotype.Repository;
     4 
     5 import com.boe.Entity.Post;
     6 
     7 @Repository("postDAO")
     8 public interface PostDAO {
     9     
    10     //public int addPost(Post post);
    11     
    12     public Post findPostById(Integer id);
    13 
    14 }

    Mapper文件中创建复杂映射关系

    刚开始只查询P_POST表中的字段,但是只有id和title可以直接映射到实体类,person和comments无从得知,但是三张表之间有关联,可以通过查询到的person_id,关联查询PERSON表中的对应信息,通过查询到的id,关联查询P_COMMENT中的title,这样目的就达成了。

    其中映射person属性时,其为实体类属性,因此使用association标签,而映射comments属性时,由于其为集合类型属性,因此使用collection标签。

    最后查询comment时,再创建了一个单独的查询,其中传入的参数为P_POST表的主键id,不是其他表的,最后查询结果映射到comments属性。

    <?xml version="1.0" en评论coding="UTF-8"?>
    <!DOCTYPE mapper
      PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
      "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="com.boe.Dao.PostDAO">
      
       <!-- 以下查询方法查询不到person,和comment -->
       <!--  
       <select id="findPostById" parameterType="int" resultType="com.boe.Entity.Post">   
         select 
          id,
          title,
          person_id
         from p_post
         where
         id=#{id}         
       </select>
       -->
       
       <!-- 如果需要查询得到person和comment,需要使用resultMap,进行处理 -->
       <select id="findPostById" parameterType="int" resultMap="postMap">   
         select 
           p_post.id,
           title,
           person_id,
           p_person.name
         from p_post
         left outer join p_person on p_person.id=person_id
         where
         p_post.id=#{id}         
       </select>
       
       <resultMap type="com.boe.Entity.Post" id="postMap">
         <!-- 逐一映射每个属性 -->
         <!-- 主键采用id映射,其他采用result映射 -->
         <id column="id" property="id"></id>
         <result column="title" property="title"></result>
         <!-- 映射person属性,由于person是个实体类属性,因此需要用association标签 -->
         <association property="person" javaType="com.boe.Entity.Person">
           <id column="person_id" property="id"></id>
           <result column="name" property="name"></result>
         </association>
         <!-- 映射comments属性,由于comments是一个集合,因此需要使用collection标签 -->
         <collection property="comments" column="id" select="findCommentsByPostId">
           
         </collection>
       </resultMap>
       
       <!-- 查询comments,单独写一个查询 -->
       <select id="findCommentsByPostId" parameterType="int" resultType="com.boe.Entity.Comment">
          select
            id,
            title,
            post_id as postId
          from p_comment      
          where post_id=#{id}
       </select>
         
    </mapper>

    测试

    基于云笔记项目中的测试类,建立单独的测试,测试结果能正常返回帖子详细信息。

     1 package Test;
     2 
     3 import org.junit.Before;
     4 import org.junit.Test;
     5 
     6 import com.boe.Dao.PostDAO;
     7 import com.boe.Entity.Post;
     8 
     9 public class testPost extends baseTest{
    10     
    11     PostDAO dao;
    12     
    13     @Before
    14     public void initTestPost() {
    15         dao=ac.getBean("postDAO",PostDAO.class);
    16     }
    17     
    18     
    19     //通过post id来查找帖子
    20     @Test
    21     public void testFindPost() {
    22         Post post=dao.findPostById(1);
    23         System.out.println(post);
    24     }
    25 
    26 }

    测试结果展示:

    结论

    (1)当查询结果包含实体类和集合时,简单的一一映射不能满足要求,需要使用MyBatis关联查询,返回类型需要使用resultMap,并在resultMap里逐一配置,映射每个属性。

    (2)如果需要映射实体类属性,使用association标签,需要映射集合类型属性,使用collection标签。

  • 相关阅读:
    HashMap(HashSet)的实现
    C/C++ 安全编码 —— 指针与内存
    AlexNet神经网络结构
    查看,修改动态组成员/通讯组
    刷新已禁用用户邮箱状态
    监控DAG状态
    AD诊断命令
    PowerShell管理Exchange
    TCP连接(Time_Wait、Close_Wait)说明
    IIS配置(安装IIS、.Net、更改IIS Log目录位置)
  • 原文地址:https://www.cnblogs.com/youngchaolin/p/10795910.html
Copyright © 2011-2022 走看看