mybatis中的多表查詢: 示例:使用者和角色 一個使用者可以有多個角色 一個角色可以賦予多個使用者 步驟: 1、建立兩張表:使用者表,角色表 讓使用者表和角色表具有多對多的關係。需要使用中間表,中間表中包含各自的主鍵,在中間表中是外來鍵。 2、建立兩個實體類:使用者實體類和角色實體類 讓使用者和角色的實體類能體現出來多對多的關係 各自包含對方一個集合引用 3、建立兩個配置檔案 使用者的配置檔案 角色的配置檔案 4、實現配置: 當我們查詢使用者時,可以同時得到使用者所包含的角色資訊 當我們查詢角色時,可以同時得到角色的所賦予的使用者資訊1234567891011121314151617
專案目錄結構實現 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 + '\'' + '}'; }}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
編寫 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();}12345678910111213141516171819202122
實現的 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 123
執行結果:
注意:sql語句換行的時候最好在每行的末尾或開頭新增空格,這樣可以防止合併成一行時發生錯誤。
編寫對映檔案IRoleDao.xml:
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()); } }}1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
執行結果:
2021-02-13 00:05:47,481 349 [ main] DEBUG ansaction.jdbc.JdbcTransaction - Opening JDBC Connection2021-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.uid2021-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 01234567891011121314151617181920
實現 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 + '}'; }}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
編寫 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();}1234567891011121314151617181920212223
實現的 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 123
執行結果:
編寫對映檔案IUserDao.xml:
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()); } }}1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
執行結果:
2021-02-13 00:17:32,971 422 [ main] DEBUG ansaction.jdbc.JdbcTransaction - Opening JDBC Connection2021-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.rid2021-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 01234567891011121314151617181920212223242526272829303132333435363738
以上就是Mybatis的多表關聯查詢(多對多)的全部內容。
最新評論