五、MyBatis中的关联关系映射
5.1 什么是关联关系映射?
关联关系是面向对象分析、面向对象设计最重要的知识。合理的关联关系将大大简化持久层数据的访问。关联关系大致分为以下几类:
- 一对一
- 一对多
- 多对一
- 多对多
5.2 一对一关联关系映射
以qqUser表和baseInfo表为例,一个qq号对应一个用户信息表,这就是我们所说的一对一关联关系。
已知QQUser实体类中包含了这5个属性值和其映射的实体类对象:
BaseInfo实体类中包含了这8个属性值:
-
qquser映射到baseinfo
association:表示关联关系,Property属性表示映射的实体类对象,column表示映射的实体类;
id:表示关联外键,property表示实体类中的属性名,column表示表中的字段名;
result:表示映射结果,property表示实体类中的属性名,column表示表中的字段名。<?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="cn.ebuy.dao.QQUserMapper"> <resultMap id="qquserMap" type="cn.ebuy.pojo.QQUser"> <result property="qqid" column="qqid"/> <result property="password" column="password"/> <result property="lastlogtime" column="lastlogtime"/> <result property="onlines" column="onlines"/> <result property="levels" column="levels"/> <!--配置关联映射--> <association property="baseInfo" column="cn.ebuy.pojo.BaseInfo"> <id property="qqid" column="qqid"/> <result property="nickname" column="nickname"/> <result property="sex" column="sex"/> <result property="age" column="age"/> <result property="province" column="province"/> <result property="city" column="city"/> <result property="address" column="address"/> <result property="phone" column="phone"/> </association> </resultMap> <!--查询所有qquser信息:qquser映射到baseinfo--> <select id="selectAll" resultMap="qquserMap"> select * from QQUSER a,baseinfo b where a.qqid=b.qqid </select> </mapper>
/** * QQUser映射接口(相当于原来的DAO接口) */ public interface QQUserMapper{ /** * 查询所有qquser信息 * @return */ List<QQUser> selectAll(); } //测试类 /** * 查找所有qquser信息 */ @Test public void selectAll(){ List<QQUser> list; SqlSession sqlSession = MyBatisUtil.createSqlSession(); QQUserMapper qqUserMapper = sqlSession.getMapper(QQUserMapper.class); list = qqUserMapper.selectAll(); for (QQUser qqUser:list){ System.out.println(qqUser); } MyBatisUtil.closeeSqlSession(sqlSession); }
-
baseinfo映射到qquser
与qquser映射到baseinfo同理。
5.3 多对一关联关系映射(在多中定义一的对象)
以用户表和角色表为例,多个用户可以共同使用这一个角色,用户与角色之间是多对一关系。
已知SystemUser3实体类:
package cn.ebuy.pojo;
import java.io.Serializable;
/**
* 用户实体
*/
public class SystemUser3 implements Serializable {
/**
* 用户ID
*/
private String userinfouid;
/**
* 登录名
*/
private String userinfologinid;
/**
* 姓名
*/
private String userinfoname;
/**
* 密码
*/
private String userinfopassword;
/**
* 性别
*/
private String userinfo_sex;
/**
* 电子邮箱
*/
private String userinfo_email;
/**
* 手机
*/
private String userinfo_mobile;
/**
* 用户状态(1 正常 2 锁定 3注销)
*/
private int userinfo_status;
/**
* 角色实体类
*/
SystemRole systemRole;
public SystemUser3() {
}
public String getUserinfouid() {
return userinfouid;
}
public void setUserinfouid(String userinfouid) {
this.userinfouid = userinfouid;
}
public String getUserinfologinid() {
return userinfologinid;
}
public void setUserinfologinid(String userinfologinid) {
this.userinfologinid = userinfologinid;
}
public String getUserinfoname() {
return userinfoname;
}
public void setUserinfoname(String userinfoname) {
this.userinfoname = userinfoname;
}
public String getUserinfopassword() {
return userinfopassword;
}
public void setUserinfopassword(String userinfopassword) {
this.userinfopassword = userinfopassword;
}
public String getUserinfo_sex() {
return userinfo_sex;
}
public void setUserinfo_sex(String userinfo_sex) {
this.userinfo_sex = userinfo_sex;
}
public String getUserinfo_email() {
return userinfo_email;
}
public void setUserinfo_email(String userinfo_email) {
this.userinfo_email = userinfo_email;
}
public String getUserinfo_mobile() {
return userinfo_mobile;
}
public void setUserinfo_mobile(String userinfo_mobile) {
this.userinfo_mobile = userinfo_mobile;
}
public int getUserinfo_status() {
return userinfo_status;
}
public void setUserinfo_status(int userinfo_status) {
this.userinfo_status = userinfo_status;
}
public SystemRole getSystemRole() {
return systemRole;
}
public void setSystemRole(SystemRole systemRole) {
this.systemRole = systemRole;
}
}
角色SystemRole实体类:
用户到角色的映射(多对一):
关联关系association中的id是在“多”的一方定义“一”的外键:
<?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="cn.ebuy.dao.SystemUserMapper">
<resultMap id="userMap3" type="cn.ebuy.pojo.SystemUser3">
<result property="userinfouid" column="userinfo_uid"/>
<result property="userinfologinid" column="userinfo_loginid"/>
<result property="userinfoname" column="userinfo_name"/>
<result property="userinfopassword" column="userinfo_password"/>
<result property="userinfo_sex" column="userinfo_sex"/>
<result property="userinfo_email" column="userinfo_email"/>
<result property="userinfo_mobile" column="userinfo_mobile"/>
<result property="userinfo_status" column="userinfo_status"/>
<!--关联映射 用户到角色的映射 多对一-->
<association property="systemRole" javaType="cn.ebuy.pojo.SystemRole2">
<id property="role_id" column="userinfo_role"/>
<result property="role_name" column="role_name"/>
<result property="role_code" column="role_code"/>
<result property="role_description" column="role_description"/>
</association>
</resultMap>
<!--关联映射 用户到角色的映射-->
<select id="selectAllByAssociation" resultMap="userMap3">
select * from system_userinfo a,system_role b where a.userinfo_role=b.role_id
</select>
</mapper>
/**
* 关联映射 用户到角色的映射
* @return
*/
List<SystemUser3> selectAllByAssociation();
//测试类
/**
* 测试关联映射 用户映射到角色
*/
@Test
public void selectAllByAssociation(){
List<SystemUser3> list;
SqlSession sqlSession = MyBatisUtil.createSqlSession();
SystemUserMapper systemUserMapper = sqlSession.getMapper(SystemUserMapper.class);
list = systemUserMapper.selectAllByAssociation();
for (SystemUser3 systemUser3:list){
System.out.println(systemUser3);
}
MyBatisUtil.closeeSqlSession(sqlSession);
}
5.4 一对多关联关系映射(在一种定义多的对象集合)
还以角色类和用户类为例,一个角色可以对应多个用户,此时角色与用户的关系为一对多关系。
已知SystemUser3实体类:
package cn.ebuy.pojo;
import java.io.Serializable;
/**
* 用户实体
*/
public class SystemUser3 implements Serializable {
/**
* 用户ID
*/
private String userinfouid;
/**
* 登录名
*/
private String userinfologinid;
/**
* 姓名
*/
private String userinfoname;
/**
* 密码
*/
private String userinfopassword;
/**
* 性别
*/
private String userinfo_sex;
/**
* 电子邮箱
*/
private String userinfo_email;
/**
* 手机
*/
private String userinfo_mobile;
/**
* 用户状态(1 正常 2 锁定 3注销)
*/
private int userinfo_status;
public SystemUser3() {
}
public String getUserinfouid() {
return userinfouid;
}
public void setUserinfouid(String userinfouid) {
this.userinfouid = userinfouid;
}
public String getUserinfologinid() {
return userinfologinid;
}
public void setUserinfologinid(String userinfologinid) {
this.userinfologinid = userinfologinid;
}
public String getUserinfoname() {
return userinfoname;
}
public void setUserinfoname(String userinfoname) {
this.userinfoname = userinfoname;
}
public String getUserinfopassword() {
return userinfopassword;
}
public void setUserinfopassword(String userinfopassword) {
this.userinfopassword = userinfopassword;
}
public String getUserinfo_sex() {
return userinfo_sex;
}
public void setUserinfo_sex(String userinfo_sex) {
this.userinfo_sex = userinfo_sex;
}
public String getUserinfo_email() {
return userinfo_email;
}
public void setUserinfo_email(String userinfo_email) {
this.userinfo_email = userinfo_email;
}
public String getUserinfo_mobile() {
return userinfo_mobile;
}
public void setUserinfo_mobile(String userinfo_mobile) {
this.userinfo_mobile = userinfo_mobile;
}
public int getUserinfo_status() {
return userinfo_status;
}
public void setUserinfo_status(int userinfo_status) {
this.userinfo_status = userinfo_status;
}
public SystemRole getSystemRole() {
return systemRole;
}
public void setSystemRole(SystemRole systemRole) {
this.systemRole = systemRole;
}
}
角色SystemRole实体类:
角色到用户的映射(一对多):
一对多的映射要在“一”中定义“多”的对象集合:collection
collection:表示映射集合,property表示外键集合对象名,ofType表示外键对象的实体类;
result表示映射结果,property表示实体类中的属性名,column表示表中的字段名。
<?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="cn.ebuy.dao.SystemRoleMapper">
<!--角色和表的映射-->
<resultMap id="roleMap" type="cn.ebuy.pojo.SystemRole2">
<result property="roleid" column="role_id"/>
<result property="rolename" column="role_name"/>
<result property="rolecode" column="role_code"/>
<result property="roledescription" column="role_description"/>
<!--配置关联关系 角色映射到用户 一对多 1-->
<!--注意:此时的多关系应该为collection集合-->
<collection property="listUser" ofType="cn.ebuy.pojo.SystemUser">
<result property="userinfo_uid" column="userinfo_uid"/>
<result property="userinfo_loginid" column="userinfo_loginid"/>
<result property="userinfo_name" column="userinfo_name"/>
<result property="userinfo_password" column="userinfo_password"/>
<result property="userinfo_sex" column="userinfo_sex"/>
<result property="userinfo_email" column="userinfo_email"/>
<result property="userinfo_mobile" column="userinfo_mobile"/>
<result property="userinfo_status" column="userinfo_status"/>
</collection>
</resultMap>
<resultMap id="roleMap2" type="cn.ebuy.pojo.SystemRole2">
<result property="roleid" column="role_id"/>
<result property="rolename" column="role_name"/>
<result property="rolecode" column="role_code"/>
<result property="roledescription" column="role_description"/>
<!--配置关联关系 角色映射到用户 一对多 2-->
<!--注意:此时的多关系应该为collection集合-->
<!--可以通过添加多个映射,然后在集合里再次映射来提高代码的复用率-->
<collection property="listUser" ofType="cn.ebuy.pojo.SystemUser" resultMap="userMap"/>
</resultMap>
<resultMap id="userMap" type="cn.ebuy.pojo.SystemUser">
<result property="userinfo_uid" column="userinfo_uid"/>
<result property="userinfo_loginid" column="userinfo_loginid"/>
<result property="userinfo_name" column="userinfo_name"/>
<result property="userinfo_password" column="userinfo_password"/>
<result property="userinfo_sex" column="userinfo_sex"/>
<result property="userinfo_email" column="userinfo_email"/>
<result property="userinfo_mobile" column="userinfo_mobile"/>
<result property="userinfo_status" column="userinfo_status"/>
</resultMap>
<!--关联映射 角色到用户的映射 一对多-->
<select id="selectAllByAssociation" resultMap="roleMap">
select * from system_userinfo a,system_role b where a.userinfo_role=b.role_id
</select>
</mapper>
/**
* 角色到用户的映射 一对多
* @return
*/
List<SystemRole2> selectAllByAssociation();
//测试类
/**
* 关联映射 角色到用户的映射 一对多
*/
@Test
public void selectAllByAssociation(){
List<SystemRole2> list;
SqlSession sqlSession = MyBatisUtil.createSqlSession();
SystemRoleMapper systemRoleMapper = sqlSession.getMapper(SystemRoleMapper.class);
list = systemRoleMapper.selectAllByAssociation();
for (SystemRole2 systemRole2:list){
System.out.println(systemRole2);
}
MyBatisUtil.closeeSqlSession(sqlSession);
}
小贴士:
当映射实体类的属性名宇宙无敌多时,我们不需要每次使用时都将其映射一遍再关联,这时我们只要将映射对象的实体类作为一个结果映射,在collection集合中再次映射即可。