Mybatis 多對多
在前麵的章節中,我們學習了一對多,多對一的關係,現在我們來看看 Mybatis 中的多對多應用。
mybatis3.0 添加了association和collection標簽專門用於對多個相關實體類數據進行級聯查詢,但仍不支持多個相關實體類數據的級聯保存和級聯刪除操作。因此在進行實體類多對多映射表設計時,需要專門建立一個關聯對象類對相關實體類的關聯關係進行描述。下文將以“User”和“Group"兩個實體類之間的多對多關聯映射為例進行CRUD操作。
1、應用場景
假設項目中存在用戶和用戶組,從一個用戶讀取出它所在的用戶組,從一個用戶組也知道這個組內的所有用戶信息。
2、先做一些準備工作
我們首先在創建一個 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中。
2、創建表對應的 JavaBean 對象
這個例子中,我們需要在包 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 http://www.gitbook.net */ 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 http://www.gitbook.net */ 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; } }
3、配置文件
在這一章節中,要用到的配置文件有四個,一個是 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 http://www.gitbook.net --> <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類。
4、測試程序運行
到這裡,整個工作準備得已經差不多了,我們創建一個主類來測試上麵程序,在 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