在前面的章節(jié)中,我們學(xué)習(xí)了一對多,多對一的關(guān)系,現(xiàn)在我們來看看 Mybatis 中的多對多應(yīng)用。
mybatis3.0 添加了association和collection標(biāo)簽專門用于對多個(gè)相關(guān)實(shí)體類數(shù)據(jù)進(jìn)行級聯(lián)查詢,但仍不支持多個(gè)相關(guān)實(shí)體類數(shù)據(jù)的級聯(lián)保存和級聯(lián)刪除操作。因此在進(jìn)行實(shí)體類多對多映射表設(shè)計(jì)時(shí),需要專門建立一個(gè)關(guān)聯(lián)對象類對相關(guān)實(shí)體類的關(guān)聯(lián)關(guān)系進(jìn)行描述。下文將以“User”和“Group"兩個(gè)實(shí)體類之間的多對多關(guān)聯(lián)映射為例進(jìn)行CRUD操作。
假設(shè)項(xiàng)目中存在用戶和用戶組,從一個(gè)用戶讀取出它所在的用戶組,從一個(gè)用戶組也知道這個(gè)組內(nèi)的所有用戶信息。
我們首先在創(chuàng)建一個(gè) java 工程,工程名稱為:mybatis06-many2many(下載),還需要?jiǎng)?chuàng)建三張表,它們分別是用戶表 user,用戶組表 group 和 用戶組映射表 user_group ,一個(gè)戶用戶可以在多個(gè)用戶組中,一個(gè)用戶組中有多個(gè)用戶。項(xiàng)目工程結(jié)構(gòu)如下:

user表的結(jié)構(gòu)和數(shù)據(jù):
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 表的結(jié)構(gòu)和數(shù)據(jù):
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 的結(jié)構(gòu)和數(shù)據(jù):
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');
從上面應(yīng)該看出,用戶ID為1同時(shí)在用戶組ID為 1 和 2 中,而用戶ID為 2 僅在一個(gè)用戶組ID為1中。
這個(gè)例子中,我們需要在包 com.yiibai.pojo 下創(chuàng)建三個(gè)類,它們分別是: User.java 、Group.java 和 UserGroup.java,讓我們一個(gè)一個(gè)地來看它們的代碼,User.java 類的代碼如下:
package com.yiibai.pojo;
import java.util.List;
/**
* @describe: User
* @author: Yiibai
* @version: V1.0
* @copyright http://www.yiibai.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 http://www.yiibai.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 類(用戶和用戶組的關(guān)系映射)的代碼如下:
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;
}
}
在這一章節(jié)中,要用到的配置文件有四個(gè),一個(gè)是 mybatis 的主配置文件:src/config/Configure.xml ,另外就是上面三個(gè)Bean類對應(yīng)的配置文件,如,User.java 對應(yīng)的配置文件 User.xml,等,我們先來看看 src/config/Configure.xml,其詳細(xì)配置信息如下:
<?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.yiibai.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 對應(yīng)的配置文件 src/com/yiibai/maper/Group.xml 的內(nèi)容如下:
<?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 對應(yīng)的配置文件 src/com/yiibai/maper/User.xml 的內(nèi)容如下:
<?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 對應(yīng)的配置文件 src/com/yiibai/maper/UserGroup.xml 的內(nèi)容如下:
<?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>
<!-- 根據(jù)一個(gè)用戶組ID,查看這個(gè)用戶組下的所有用戶 -->
<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>
<!-- 根據(jù)一個(gè)用戶ID,查看這個(gè)用戶所對應(yīng)的組-->
<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>標(biāo)簽,關(guān)聯(lián)對應(yīng)的 User 類和 Group類。
到這里,整個(gè)工作準(zhǔn)備得已經(jīng)差不多了,我們創(chuàng)建一個(gè)主類來測試上面程序,在 src 下創(chuàng)建一個(gè) 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();
}
}
}
運(yùn)行上述程序,得出結(jié)果:
Group => Group-1 :1 yiibai :2 User-name-1