在前面的章節中,我們學習了一對多,多對一的關係,現在我們來看看 Mybatis 中的多對多應用。
mybatis3.0 新增了association和collection標籤專門用於對多個相關實體類資料進行級聯查詢,但仍不支援多個相關實體類資料的級聯儲存和級聯刪除操作。因此在進行實體類多對多對映表設計時,需要專門建立一個關聯物件類對相關實體類的關聯關係進行描述。下文將以「User」和「Group"兩個實體類之間的多對多關聯對映為例進行CRUD操作。
假設專案中存在使用者和使用者組,從一個使用者讀取出它所在的使用者組,從一個使用者組也知道這個組內的所有使用者資訊。
我們首先在建立一個 java 工程,工程名稱為:mybatis06-many2many(下載),還需要建立三張表,它們分別是使用者表 user,使用者組表 group 和 使用者組對映表 user_group ,一個戶使用者可以在多個使用者組中,一個使用者組中有多個使用者。專案工程結構如下:
user表的結構和資料:
CREATE TABLE `user` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `username` varchar(64) NOT NULL DEFAULT '', `mobile` varchar(16) NOT NULL DEFAULT '', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of user -- ---------------------------- INSERT INTO `user` VALUES ('1', 'yiibai', '13838009988'); INSERT INTO `user` VALUES ('2', 'User-name-1', '13838009988');
使用者組 group 表的結構和資料:
CREATE TABLE `group` ( `group_id` int(10) unsigned NOT NULL AUTO_INCREMENT, `group_name` varchar(254) NOT NULL DEFAULT '', PRIMARY KEY (`group_id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of group -- ---------------------------- INSERT INTO `group` VALUES ('1', 'Group-1'); INSERT INTO `group` VALUES ('2', 'Group-2');使用者組對映表 user_group 的結構和資料:
CREATE TABLE `user_group` ( `user_id` int(10) unsigned NOT NULL DEFAULT '0', `group_id` int(10) unsigned NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of user_group -- ---------------------------- INSERT INTO `user_group` VALUES ('1', '1'); INSERT INTO `user_group` VALUES ('2', '1'); INSERT INTO `user_group` VALUES ('1', '2');
從上面應該看出,使用者ID為1同時在使用者組ID為 1 和 2 中,而使用者ID為 2 僅在一個使用者組ID為1中。
這個例子中,我們需要在包 com.yiibai.pojo 下建立三個類,它們分別是: User.java 、Group.java 和 UserGroup.java,讓我們一個一個地來看它們的程式碼,User.java 類的程式碼如下:
package com.yiibai.pojo; import java.util.List; /** * @describe: User * @author: Yiibai * @version: V1.0 * @copyright https://www.tw511.com */ public class User { private int id; private String username; private String mobile; private List<Group> groups; public List<Group> getGroups() { return groups; } public void setGroups(List<Group> groups) { this.groups = groups; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getMobile() { return mobile; } public void setMobile(String mobile) { this.mobile = mobile; } }Group.java 類的程式碼如下:
package com.yiibai.pojo; import java.util.List; /** * @describe: Group * @author: Yiibai * @version: V1.0 * @copyright https://www.tw511.com */ public class Group { private int groupId; private String groupName; private List<User> users; public List<User> getUsers() { return users; } public void setUsers(List<User> users) { this.users = users; } public int getGroupId() { return groupId; } public void setGroupId(int groupId) { this.groupId = groupId; } public String getGroupName() { return groupName; } public void setGroupName(String groupName) { this.groupName = groupName; } }UserGroup.java 類(使用者和使用者組的關係對映)的程式碼如下:
package com.yiibai.pojo; public class UserGroup { private int userId; private int groupId; public int getUserId() { return userId; } public void setUserId(int userId) { this.userId = userId; } public int getGroupId() { return groupId; } public void setGroupId(int groupId) { this.groupId = groupId; } }
在這一章節中,要用到的組態檔案有四個,一個是 mybatis 的主組態檔案:src/config/Configure.xml ,另外就是上面三個Bean類對應的組態檔案,如,User.java 對應的組態檔案 User.xml,等,我們先來看看 src/config/Configure.xml,其詳細組態資訊如下:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <typeAliases> <typeAlias alias="User" type="com.yiibai.pojo.User" /> <typeAlias alias="UserGroup" type="com.yiibai.pojo.UserGroup" /> <typeAlias alias="Group" type="com.yiibai.pojo.Group" /> </typeAliases> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://127.0.0.1:3306/yiibai" /> <property name="username" value="root" /> <property name="password" value="" /> </dataSource> </environment> </environments> <mappers> <!-- // power by https://www.tw511.com --> <mapper resource="com/yiibai/maper/UserMaper.xml" /> <mapper resource="com/yiibai/maper/GroupMaper.xml" /> <mapper resource="com/yiibai/maper/UserGroupMaper.xml" /> </mappers> </configuration>Group.java 對應的組態檔案 src/com/yiibai/maper/Group.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.yiibai.maper.GroupMaper"> <parameterMap type="Group" id="parameterGroupMap"> <parameter property="groupId"/> <parameter property="groupName"/> </parameterMap> <insert id="insertGroup" parameterMap="parameterGroupMap"> INSERT INTO `group` (group_name) VALUES(#{groupName}); </insert> <resultMap type="Group" id="resultGroupMap_1"> <result property="id" column="id" /> <result property="groupName" column="group_name" /> <collection property="users" column="group_id" select="com.yiibai.maper.UserGroupMaper.getUsersByGroupId" /> </resultMap> <select id="getGroup" resultMap="resultGroupMap_1" parameterType="int"> SELECT * FROM `group` WHERE group_id=#{id} </select> </mapper>
User.java 對應的組態檔案 src/com/yiibai/maper/User.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.yiibai.maper.UserMaper"> <parameterMap type="User" id="parameterUserMap"> <parameter property="id"/> <parameter property="username"/> <parameter property="mobile"/> </parameterMap> <insert id="insertUser" parameterMap="parameterUserMap"> INSERT INTO user(username,mobile) VALUES(#{username},#{mobile}); </insert> <resultMap type="User" id="resultUser"> <result property="id" column="group_id"/> <result property="name" column="name"/> <collection property="groups" column="id" select="com.yiibai.maper.UserGroupMaper.getGroupsByUserId"/> </resultMap> <select id="getUser" resultMap="resultUser" parameterType="int"> SELECT * FROM user WHERE id=#{id} </select> </mapper>UserGroup.java 對應的組態檔案 src/com/yiibai/maper/UserGroup.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.yiibai.maper.UserGroupMaper"> <parameterMap type="UserGroup" id="parameterUserGroupMap"> <parameter property="userId"/> <parameter property="groupId"/> </parameterMap> <insert id="insertUserGroup" parameterMap="parameterUserGroupMap"> INSERT INTO user_group(user_id, group_id) VALUES(#{userId},#{groupId}) </insert> <!-- 根據一個使用者組ID,檢視這個使用者組下的所有使用者 --> <resultMap type="User" id="resultUserMap_2"> <result property="id" column="id"/> <result property="username" column="username"/> <result property="mobile" column="mobile"/> </resultMap> <select id="getUsersByGroupId" resultMap="resultUserMap_2" parameterType="int"> SELECT u.*, ug.group_id FROM user u, user_group ug WHERE u.id=ug.user_id AND ug.group_id=#{group_id} </select> <!-- 根據一個使用者ID,檢視這個使用者所對應的組--> <resultMap type="Group" id="resultGroupMap_2"> <result property="groupId" column="group_id"/> <result property="groupName" column="group_name"/> </resultMap> <select id="getGroupsByUserId" resultMap="resultGroupMap_2" parameterType="int"> SELECT g.*, u.user_id FROM group g, user_group u WHERE g.group_id=u.group_id AND u.user_id=#{user_id} </select> </mapper>
註:在上面的組態檔案中,使用到了 <association>和 <clollection>標籤,關聯對應的 User 類和 Group類。
到這裡,整個工作準備得已經差不多了,我們建立一個主類來測試上面程式,在 src 下建立一個 Main.java,程式碼如下:
import java.io.Reader; import java.text.MessageFormat; import java.util.List; 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 com.yiibai.maper.GroupMaper; import com.yiibai.maper.UserGroupMaper; import com.yiibai.maper.UserMaper; import com.yiibai.pojo.Group; import com.yiibai.pojo.User; import com.yiibai.pojo.UserGroup; public class Main { private static SqlSessionFactory sqlSessionFactory; private static Reader reader; static { try { reader = Resources.getResourceAsReader("config/Configure.xml"); sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); } catch (Exception e) { e.printStackTrace(); } } public static SqlSessionFactory getSession() { return sqlSessionFactory; } /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub // testAddGroup(); // testAddUser(); // testAddUserGroup(); testGetGroupAndUsers(); } public static void testGetGroupAndUsers() { UserGroup userGroup = new UserGroup(); SqlSession session = sqlSessionFactory.openSession(); try { GroupMaper groupMaper = session.getMapper(GroupMaper.class); Group group = groupMaper.getGroup(1); System.out.println("Group => " + group.getGroupName()); List<User> users = group.getUsers(); for (User user : users) { System.out.println("\t:" + user.getId() + "\t" + user.getUsername()); } } finally { session.close(); } } public static void testAddUserGroup() { UserGroup userGroup = new UserGroup(); userGroup.setGroupId(1); userGroup.setUserId(2); SqlSession session = sqlSessionFactory.openSession(); try { UserGroupMaper userGroupMaper = session .getMapper(UserGroupMaper.class); userGroupMaper.insertUserGroup(userGroup); session.commit(); } finally { session.close(); } } public static void testAddUser() { // TODO Auto-generated method stub SqlSession session = sqlSessionFactory.openSession(); try { User user = new User(); user.setUsername("User-name-1"); user.setMobile("13838009988"); UserMaper userMaper = session.getMapper(UserMaper.class); userMaper.insertUser(user); session.commit(); // System.out.println(user.getGroupId()); } finally { session.close(); } } public static void testAddGroup() { // TODO Auto-generated method stub SqlSession session = sqlSessionFactory.openSession(); try { Group group = new Group(); group.setGroupName("使用者組-1"); GroupMaper groupMapper = session.getMapper(GroupMaper.class); groupMapper.insertGroup(group); session.commit(); System.out.println(group.getGroupId()); } finally { session.close(); } } }
執行上述程式,得出結果:
Group => Group-1 :1 yiibai :2 User-name-1