Mybatis的多表關聯查詢(多對多)
- 專案目錄結構
- 實作 Role 到 User 多對多
- 業務要求
- 用戶與角色的關系模型
- 撰寫角色物體類
- 撰寫 Role 持久層介面
- 實作的 SQL 陳述句
- 撰寫映射檔案
- 測驗代碼
- 實作 User 到 Role 的多對多
- 業務要求
- 撰寫用戶物體類
- 撰寫 User持久層介面
- 實作的 SQL 陳述句
- 撰寫映射檔案
- 測驗代碼
mybatis中的多表查詢:
示例:用戶和角色
一個用戶可以有多個角色
一個角色可以賦予多個用戶
步驟:
1、建立兩張表:用戶表,角色表
讓用戶表和角色表具有多對多的關系,需要使用中間表,中間表中包含各自的主鍵,在中間表中是外鍵,
2、建立兩個物體類:用戶物體類和角色物體類
讓用戶和角色的物體類能體現出來多對多的關系
各自包含對方一個集合參考
3、建立兩個組態檔
用戶的組態檔
角色的組態檔
4、實作配置:
當我們查詢用戶時,可以同時得到用戶所包含的角色資訊
當我們查詢角色時,可以同時得到角色的所賦予的用戶資訊
專案目錄結構

實作 Role 到 User 多對多
多對多關系其實我們看成是雙向的一對多關系,
業務要求
需求:
當我們查詢角色時,可以同時得到角色的所賦予的用戶資訊,
分析:
查詢角色我們需要用到Role表,但角色分配的用戶的資訊我們并不能直接找到用戶資訊,而是要通過中間表(USER_ROLE 表)才能關聯到用戶資訊,
用戶與角色的關系模型
用戶與角色的多對多關系模型如下:
角色表:

用戶表:

用戶角色中間表:

撰寫角色物體類
Role:
package com.keafmd.domain;
import java.io.Serializable;
import java.util.List;
/**
* Keafmd
*
* @ClassName: Role
* @Description: 角色物體類
* @author: 牛哄哄的柯南
* @date: 2021-02-12 16:45
*/
public class Role implements Serializable {
private Integer roleId;
private String roleName;
private String roleDesc;
//多對多的關系映射
private List<User> users;
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
public Integer getRoleId() {
return roleId;
}
public void setRoleId(Integer roleId) {
this.roleId = roleId;
}
public String getRoleName() {
return roleName;
}
public void setRoleName(String roleName) {
this.roleName = roleName;
}
public String getRoleDesc() {
return roleDesc;
}
public void setRoleDesc(String roleDesc) {
this.roleDesc = roleDesc;
}
@Override
public String toString() {
return "Role{" +
"roleId=" + roleId +
", roleName='" + roleName + '\'' +
", roleDesc='" + roleDesc + '\'' +
'}';
}
}
撰寫 Role 持久層介面
IRoleDao:
package com.keafmd.dao;
import com.keafmd.domain.Role;
import java.util.List;
/**
* Keafmd
*
* @ClassName: IRoleDao
* @Description:
* @author: 牛哄哄的柯南
* @date: 2021-02-12 19:01
*/
public interface IRoleDao {
/**
* 查詢所有角色
* @return
*/
List<Role> findAll();
}
實作的 SQL 陳述句
select u.*,r.id as rid ,r.role_name ,r.role_desc from role r
left outer join user_role ur on r.id = ur.rid
left outer join user u on u.id=ur.uid
執行結果:

注意:sql陳述句換行的時候最好在每行的末尾或開頭添加空格,這樣可以防止合并成一行時發生錯誤,
撰寫映射檔案
IRoleDao.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.keafmd.dao.IRoleDao">
<!--定義role表的resultmap-->
<resultMap id="roleMap" type="role">
<id property="roleId" column="rid"></id>
<result property="roleName" column="role_name"></result>
<result property="roleDesc" column="role_desc"></result>
<collection property="users" ofType="user">
<id column="id" property="id"></id>
<result column="username" property="username"></result>
<result column="address" property="address"></result>
<result column="sex" property="sex"></result>
<result column="birthday" property="birthday"></result>
</collection>
</resultMap>
<!--查詢所有-->
<select id="findAll" resultMap="roleMap">
select u.*,r.id as rid ,r.role_name ,r.role_desc from role r
left outer join user_role ur on r.id = ur.rid
left outer join user u on u.id=ur.uid
</select>
</mapper>
測驗代碼
RoleTest:
package com.keafmd.test;
import com.keafmd.dao.IRoleDao;
import com.keafmd.dao.IUserDao;
import com.keafmd.domain.Role;
import com.keafmd.domain.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.InputStream;
import java.util.List;
/**
* Keafmd
*
* @ClassName: MybatisTest
* @Description: 測驗類,測驗crud操作
* @author: 牛哄哄的柯南
* @date: 2021-02-08 15:24
*/
public class RoleTest {
private InputStream in;
private SqlSession sqlsession;
private IRoleDao roleDao;
@Before // 用于在測驗方法執行前執行
public void init()throws Exception{
//1.讀取組態檔,生成位元組輸入流
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.創建SqlSessionFactory工廠
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
//3.使用工廠生產SqlSession物件
sqlsession = factory.openSession(); //里面寫個true,下面每次就不用了寫 sqlsession.commit(); 了
//4.使用SqlSession創建Dao介面的代理物件
roleDao = sqlsession.getMapper(IRoleDao.class);
}
@After // 用于在測驗方法執行后執行
public void destory() throws Exception{
//提交事務
sqlsession.commit();
//6.釋放資源
sqlsession.close();
in.close();
}
/**
* 查詢所有
* @throws Exception
*/
@Test
public void testFindAll() {
List<Role> roles = roleDao.findAll();
for (Role role : roles) {
System.out.println("--------每個角色的資訊---------");
System.out.println(role);
System.out.println(role.getUsers());
}
}
}
運行結果:
2021-02-13 00:05:47,481 349 [ main] DEBUG ansaction.jdbc.JdbcTransaction - Opening JDBC Connection
2021-02-13 00:05:47,784 652 [ main] DEBUG source.pooled.PooledDataSource - Created connection 1027007693.
2021-02-13 00:05:47,784 652 [ main] DEBUG ansaction.jdbc.JdbcTransaction - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3d36e4cd]
2021-02-13 00:05:47,791 659 [ main] DEBUG om.keafmd.dao.IRoleDao.findAll - ==> Preparing: select u.*,r.id as rid ,r.role_name ,r.role_desc from role r left outer join user_role ur on r.id = ur.rid left outer join user u on u.id=ur.uid
2021-02-13 00:05:47,842 710 [ main] DEBUG om.keafmd.dao.IRoleDao.findAll - ==> Parameters:
2021-02-13 00:05:47,869 737 [ main] DEBUG om.keafmd.dao.IRoleDao.findAll - <== Total: 4
--------每個角色的資訊---------
Role{roleId=1, roleName='院長', roleDesc='管理整個學院'}
[User{id=41, username='老王', sex='男', address='北京', birthday=Tue Feb 27 17:47:08 CST 2018}, User{id=45, username='新一', sex='男', address='北京', birthday=Sun Mar 04 12:04:06 CST 2018}]
--------每個角色的資訊---------
Role{roleId=2, roleName='總裁', roleDesc='管理整個公司'}
[User{id=41, username='老王', sex='男', address='北京', birthday=Tue Feb 27 17:47:08 CST 2018}]
--------每個角色的資訊---------
Role{roleId=3, roleName='校長', roleDesc='管理整個學校'}
[]
2021-02-13 00:05:47,871 739 [ main] DEBUG ansaction.jdbc.JdbcTransaction - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3d36e4cd]
2021-02-13 00:05:47,872 740 [ main] DEBUG ansaction.jdbc.JdbcTransaction - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@3d36e4cd]
2021-02-13 00:05:47,872 740 [ main] DEBUG source.pooled.PooledDataSource - Returned connection 1027007693 to pool.
Process finished with exit code 0
實作 User 到 Role 的多對多
業務要求
需求:
當我們查詢用戶時,可以同時得到用戶所包含的角色資訊,
分析:
相比上面的實作 Role 到 User 多對多,主要變化就是sql陳述句的變化,
撰寫用戶物體類
User:
package com.keafmd.domain;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* Keafmd
*
* @ClassName: User
* @Description:
* @author: 牛哄哄的柯南
* @date: 2021-02-08 15:16
*/
public class User implements Serializable {
private Integer id;
private String username;
private String sex;
private String address;
private Date birthday;
//多對多的關系映射,一個用戶可以具備多個角色
private List<Role> roles;
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", sex='" + sex + '\'' +
", address='" + address + '\'' +
", birthday=" + birthday +
'}';
}
}
撰寫 User持久層介面
IUserDao:
package com.keafmd.dao;
import com.keafmd.domain.User;
import java.util.List;
/**
* Keafmd
*
* @ClassName: IUserDao
* @Description: 用戶的持久層介面
* @author: 牛哄哄的柯南
* @date: 2021-02-06 19:29
*/
public interface IUserDao {
/**
* 查詢所有用戶,同時獲取到用戶下所有賬戶的資訊
* @return
*/
List<User> findAll();
}
實作的 SQL 陳述句
select u.*,r.id as rid ,r.role_name ,r.role_desc from user u
left outer join user_role ur on u.id = ur.uid
left outer join role r on r.id=ur.rid
執行結果:

撰寫映射檔案
IUserDao.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.keafmd.dao.IUserDao">
<!--定義User的resultMap-->
<resultMap id="userMap" type="user">
<id property="id" column="id"></id>
<result property="username" column="username"></result>
<result property="address" column="address"></result>
<result property="sex" column="sex"></result>
<result property="birthday" column="birthday"></result>
<!--配置角色集合的映射-->
<collection property="roles" ofType="role">
<id property="roleId" column="rid"></id>
<result property="roleName" column="role_name"></result>
<result property="roleDesc" column="role_desc"></result>
</collection>
</resultMap>
<!--配置查詢所有-->
<select id="findAll" resultMap="userMap">
select u.*,r.id as rid ,r.role_name ,r.role_desc from user u
left outer join user_role ur on u.id = ur.uid
left outer join role r on r.id=ur.rid
</select>
</mapper>
測驗代碼
UserTest :
package com.keafmd.test;
import com.keafmd.dao.IUserDao;
import com.keafmd.domain.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.InputStream;
import java.util.List;
/**
* Keafmd
*
* @ClassName: MybatisTest
* @Description: 測驗類,測驗crud操作
* @author: 牛哄哄的柯南
* @date: 2021-02-08 15:24
*/
public class UserTest {
private InputStream in;
private SqlSession sqlsession;
private IUserDao userDao;
@Before // 用于在測驗方法執行前執行
public void init()throws Exception{
//1.讀取組態檔,生成位元組輸入流
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//2.創建SqlSessionFactory工廠
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
//3.使用工廠生產SqlSession物件
sqlsession = factory.openSession(); //里面寫個true,下面每次就不用了寫 sqlsession.commit(); 了
//4.使用SqlSession創建Dao介面的代理物件
userDao = sqlsession.getMapper(IUserDao.class);
}
@After // 用于在測驗方法執行后執行
public void destory() throws Exception{
//提交事務
sqlsession.commit();
//6.釋放資源
sqlsession.close();
in.close();
}
/**
* 查詢所有
* @throws Exception
*/
@Test
public void testFindAll() {
List<User> users = userDao.findAll();
for (User user : users) {
System.out.println("--------每個用戶的資訊---------");
System.out.println(user);
System.out.println(user.getRoles());
}
}
}
運行結果:
2021-02-13 00:17:32,971 422 [ main] DEBUG ansaction.jdbc.JdbcTransaction - Opening JDBC Connection
2021-02-13 00:17:33,275 726 [ main] DEBUG source.pooled.PooledDataSource - Created connection 1027007693.
2021-02-13 00:17:33,275 726 [ main] DEBUG ansaction.jdbc.JdbcTransaction - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3d36e4cd]
2021-02-13 00:17:33,280 731 [ main] DEBUG om.keafmd.dao.IUserDao.findAll - ==> Preparing: select u.*,r.id as rid ,r.role_name ,r.role_desc from user u left outer join user_role ur on u.id = ur.uid left outer join role r on r.id=ur.rid
2021-02-13 00:17:33,319 770 [ main] DEBUG om.keafmd.dao.IUserDao.findAll - ==> Parameters:
2021-02-13 00:17:33,343 794 [ main] DEBUG om.keafmd.dao.IUserDao.findAll - <== Total: 10
--------每個用戶的資訊---------
User{id=41, username='老王', sex='男', address='北京', birthday=Tue Feb 27 17:47:08 CST 2018}
[Role{roleId=1, roleName='院長', roleDesc='管理整個學院'}, Role{roleId=2, roleName='總裁', roleDesc='管理整個公司'}]
--------每個用戶的資訊---------
User{id=42, username='update', sex='男', address='XXXXXXX', birthday=Mon Feb 08 19:37:31 CST 2021}
[]
--------每個用戶的資訊---------
User{id=43, username='小二王', sex='女', address='北京', birthday=Sun Mar 04 11:34:34 CST 2018}
[]
--------每個用戶的資訊---------
User{id=45, username='新一', sex='男', address='北京', birthday=Sun Mar 04 12:04:06 CST 2018}
[Role{roleId=1, roleName='院長', roleDesc='管理整個學院'}]
--------每個用戶的資訊---------
User{id=50, username='Keafmd', sex='男', address='XXXXXXX', birthday=Mon Feb 08 15:44:01 CST 2021}
[]
--------每個用戶的資訊---------
User{id=51, username='update DAO', sex='男', address='XXXXXXX', birthday=Tue Feb 09 11:31:38 CST 2021}
[]
--------每個用戶的資訊---------
User{id=52, username='Keafmd DAO', sex='男', address='XXXXXXX', birthday=Tue Feb 09 11:29:41 CST 2021}
[]
--------每個用戶的資訊---------
User{id=53, username='Keafmd laset insertid 1', sex='男', address='XXXXXXX', birthday=Fri Feb 12 20:53:46 CST 2021}
[]
--------每個用戶的資訊---------
User{id=54, username='Keafmd laset insertid 2 auto', sex='男', address='XXXXXXX', birthday=Fri Feb 12 21:02:12 CST 2021}
[]
2021-02-13 00:17:33,345 796 [ main] DEBUG ansaction.jdbc.JdbcTransaction - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@3d36e4cd]
2021-02-13 00:17:33,346 797 [ main] DEBUG ansaction.jdbc.JdbcTransaction - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@3d36e4cd]
2021-02-13 00:17:33,346 797 [ main] DEBUG source.pooled.PooledDataSource - Returned connection 1027007693 to pool.
Process finished with exit code 0
以上就是Mybatis的多表關聯查詢(多對多)的全部內容,
看完如果對你有幫助,感謝點贊支持!
如果你是電腦端的話,看到右下角的 “一鍵三連” 了嗎,沒錯點它[哈哈]

加油!
共同努力!
Keafmd
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/259463.html
標籤:java

