mybatis多表查詢之多對多關係查詢的實現-xml方式

  • 2019 年 10 月 3 日
  • 筆記

  Mybatis對於多對多關係下的查詢提供了集合(collection)的概念來解決,collection屬性是resultMap高級結果映射的子集,首先,在本例中我們使用的是集合元素來解決多對多的查詢。 然後你會注意到有一個新的 “ofType” 屬性。這個屬性非常重要,它用來將 JavaBean(或欄位)屬性的類型和集合存儲的類型區分開來。在集合中ofType指的是集合中元素的類型。

  首先介紹一下Demo情況:

  • 實體類:User(用戶)類和Role(角色)類,類中的屬性在後面程式碼中貼出
  • 關係:一個用戶可以有多個角色,一個角色可以賦予多個用戶中
  • 資料庫表結構:用戶表、角色表、中間表(用於存儲用戶和角色的關係)
  • 本例中實現查詢的目標:查詢用戶時同時獲取用戶所擁有的角色的資訊(當查詢角色時同時獲取角色所屬用戶的資訊的情況和下面的例子原理一樣,主要是修改select中的sql語句)

  1.用戶實體類以及角色實體類

public class User implements Serializable{      private Integer id;      private String username;      private Date birthday;      private String sex;      private String address;      private List<Role> roles;        get和set方法省略 ......  }  public class Role implements Serializable{      private Integer roleId;      private String roleName;      private String roleDesc;      private List<User> users;       get和set方法省略 ......  }    

  這裡主要是增加用戶所擁有的角色的List屬性和角色所屬用戶的List屬性,後面做resultMap結果映射的時候使用。

    2.資料庫表結構

DROP TABLE IF EXISTS user;  CREATE TABLE user (      id INT(11) NOT NULL auto_increment,      username VARCHAR(32) NOT NULL COMMENT '用戶名稱',      birthday datetime default NULL COMMENT '生日',      sex char(1) default NULL COMMENT '性別',      address varchar(256) default NULL COMMENT '地址',      PRIMARY KEY (id)  )ENGINE=InnoDB default CHARSET=utf8  INSERT INTO `user` VALUES ('41', '老王', '2018-02-27 17:47:08', '男', '石家莊');  INSERT INTO `user` VALUES ('45', '老李', '2018-02-27 17:47:08', '男', '石家莊');  INSERT INTO `user` VALUES ('46', '老郭', '2018-02-27 17:47:08', '男', '石家莊');  INSERT INTO `user` VALUES ('47', 'mde', '2019-06-26 15:04:25', '女', '河南');  INSERT INTO `user` VALUES ('48', 'nan', '2019-08-01 15:04:54', '女', '合肥');        DROP TABLE IF EXISTS role;  CREATE TABLE role(  ID int(11) NOT NULL COMMENT '編號',  ROLE_NAME VARCHAR(30) DEFAULT NULL COMMENT '角色名稱',  ROLE_DESC VARCHAR(60) DEFAULT NULL COMMENT  '角色描述',  PRIMARY KEY (ID)  )ENGINE=INNODB DEFAULT CHARSET=utf8    INSERT INTO role (ID,ROLE_NAME,ROLE_DESC) VALUES (1,'院長','管理整個學院'),(2,'總裁','管理整個公司'),(3,'校長','管理整個學校');      DROP TABLE IF EXISTS user_role;  CREATE TABLE user_role(  UID int(11) NOT NULL COMMENT '用戶編號',  RID INT(11) NOT NULL COMMENT '角色編號',  PRIMARY KEY (UID,RID),  CONSTRAINT FK_Reference_10 FOREIGN KEY(RID) REFERENCES role(ID),  CONSTRAINT FK_Reference_9 FOREIGN KEY(UID) REFERENCES user(id)  )ENGINE=INNODB DEFAULT CHARSET=utf8;  INSERT INTO user_role(UID,RID) VALUES(41,1),(45,1),(41,2);

這裡主要是增加了中間表。

   3.在UserDao介面中聲明查詢所有用戶的方法findAll();

    /**       * 查詢所有的用戶同時查詢出所擁有的角色的資訊       *       * @return       */      List<User> findAll();

  4.在UserDao.xml中配置findAll()方法

<!DOCTYPE mapper          PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"          "http://mybatis.org/dtd/mybatis-3-mapper.dtd">  <mapper namespace="com.example.dao.UserDao">      <resultMap id="userMap" type="com.example.domain.User">          <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="roles" ofType="com.example.domain.Role" resultMap="roleMap"/>      </resultMap>      <resultMap id="roleMap" type="com.example.domain.Role">          <id property="roleId" column="rid"/>          <result property="roleName" column="ROLE_NAME"/>          <result property="roleDesc" column="ROLE_DESC"/>      </resultMap>      <select id="findAll" resultMap="userMap">         SELECT u.*,r.ID as rid,r.ROLE_DESC,r.ROLE_NAME FROM user u           LEFT OUTER JOIN user_role ur on u.id = ur.UID            LEFT OUTER JOIN role r on ur.RID = r.ID      </select>  </mapper>

  實現多對多關係查詢的主要工作都放在了這裡,首先通過resultMap 聲明用戶類的結果映射,id以及result等標籤就是User類中的基本屬性,User類中的角色屬性roles通過collection集合標籤來映射到結果集中,<collection property=”roles” ofType=”com.example.domain.Role” resultMap=”roleMap”/>,property對應User類中聲明的roles屬性,ofType用於標識集合中元素的類型,resultMap用於引用其他的結果映射來說明集合中元素的屬性,在這裡為roleMap。如果roleMap不在其他地方使用,也可以直接將角色的屬性直接配置在collection屬性的子集里,如以下形式也可以使用。

    <resultMap id="userMap" type="com.example.domain.User">          <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="roles" ofType="com.example.domain.Role" resultMap="roleMap"/>-->          <collection property="roles" ofType="com.example.domain.Role">
        <!--這裡的rid是role表中的id,在select語句中為了防止id欄位在兩個表中都出現導致的重複,所以給role的欄位id 起了別名 注意要與select中的別名保持一致--> <id property="roleId" column="rid"/> <result property="roleName" column="ROLE_NAME"/> <result property="roleDesc" column="ROLE_DESC"/> </collection> </resultMap>

 select中的SQL查詢語句解釋:

 <select id="findAll" resultMap="userMap">         SELECT u.*,r.ID as rid,r.ROLE_DESC,r.ROLE_NAME FROM user u           LEFT OUTER JOIN user_role ur on u.id = ur.UID            LEFT OUTER JOIN role r on ur.RID = r.ID      </select>

  u.*:查詢USER表中所有的屬性

  r.ID as rid:對於role表中的id起一個別名rid

  user u LEFT OUTER JOIN user_role ur on u.id = ur.UID:前面的表左連接後面的表,並且連接條件是User表中的id與User_role表中的uid相等

  5.測試程式碼

 1 public class UserDaoTest {   2     private InputStream in;   3     private SqlSession session;   4   5     private UserDao userDao;   6     private SqlSessionFactory factory;   7     @Before   8     public void init()throws Exception{   9         //獲取配置文件  10         in = Resources.getResourceAsStream("SqlMapConfig.xml");  11         //獲取工廠  12         factory = new SqlSessionFactoryBuilder().build(in);  13  14         session = factory.openSession();  15  16         userDao = session.getMapper(UserDao.class);  17     }  18     @After  19     public void destory()throws Exception{  20         session.commit();  21         session.close();  22         in.close();  23     }  24     @Test  25     public void findAllTest(){  26         List<User> userList = userDao.findAll();  27         for (User user: userList){  28             System.out.println("每個用戶的資訊");  29             System.out.println(user);  30             System.out.println(user.getRoles());  31         }  32     }

View Code

6.測試結果