MyBatis 3(4)关联映射:一对一,一对多

本文介绍了MyBatis中如何配置一对一和一对多关联映射,包括使用<association>和<collection>标签的方法,展示了具体的XML配置示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

MyBatis 关联映射


MyBatis 中对一对一,一对多的关联映射关系的配置方式是比较简单的,只需要在 XML 实体映射文件中进行相应的简单配置即可;

以下为示例代码中数据库的结构:
 
# 用户表
table user(
    user_id primary key,
    user_name,
    user_eamil,
    role_id refrences role(role_id)
)
# 角色表
table role(
    role_id primary key,
    role_name,
    role_group
    )
# 用户评论表
table comments(
    comment_id primary key,
    comment_content,
    user_id references user(user_id)
    )
其中 user 和 role 为一对一的关联关系;user 和 comments 为一对多的关联关系;




一对一映射


user 和 role 为一对一的关联关系,在 POJO User 的数据域中含有一个 Role,如下:
site.assad.domain.User
 
public class User implements Serializable{
    private int id;
    private String name;
    private String email;
    private Role role;                     //一对一关系关联映射对象属性
    // getter,setter
}
site.assad.domain.Role
 
public class Role implements Serializable {
    private int id;
    private String name;
    private String group;
    // getter,setter
}

可以使用 <association> 标签来配置一对一的关联映射,该标签含有的属性如下:
  • property:必填,对应 POJO 中的属性名称;
  • javaType:属性对应的 Java 类型;
  • resultMap:可以通过该属性直接使用现有的 resultMap;
  • columnPrefix:查询列的前缀,配置该属性后,在子标签配置 result 的 column 时可以设置该前缀值;
  • fetchType:抓取策略,可选值由 lazy(延迟抓取),eager(立即抓取);

以下是映射文件的一个示例的配置, mapper/UserMapper.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="site.assad.dao.UserDao">
    
    <!--User 的基本实体映射-->
    <resultMap id="userMap" type="site.assad.domain.User">
        <id property="id" column="user_id" />
        <result property="name" column="user_name" />
        <result property="email" column="user_email" />
    </resultMap>
    
    <!--User 一对一关联属性 role 的属性映射 -->
    <resultMap id="userRoleMap" extends="userMap" type="site.assad.domain.User">
        <!--Role 相关属性映射-->
        <association property="role" javaType="site.assad.domain.Role" >
            <id property="id" column="role_id" />
            <result property="name" column="role_name" />
            <result property="group" column="role_group" />
        </association>
    </resultMap>
    
     <!--示例一对一关联映射查询接口方法-->
    <select id="getUserByIdWithRole" resultMap="userRoleMap">
        select u.user_id, u.user_name, u.user_email,
                r.role_id, r.role_name, r.role_group
        from user u
        inner join role r on u.role_id = r.role_id
        where u.user_id = #{id}
    </select>
</mapper>

在Dao接口 site.assad.dao.UserDao 中定义接口方法:
 
public interface UserDao {
    User getUserByIdWithRole(int id);
}

以下是dao接口方法的测试代码:
 
public class UnitTest {
    private UserDao userDao;
    @Before
    public void init() throws IOException {
        Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        userDao = sqlSession.getMapper(UserDao.class);
        reader.close();
    }
    @Test
    public void testGetUserByIdWithRole(){
        User user  = userDao.getUserByIdWithRole(1);
        System.out.println(user);
    }
}




一对多映射


user 和 comment 为一对多的关联关系,在 POJO User 数据域含有一个 Comment 类型的列表属性,如下:
site.assad.domain.User
 
public class User implements Serializable{
    private int id;
    private String name;
    private String email;
    private List<Comment> comments;    //一对多的关联映射对象属性
    // getter,setter
}
site.assad.domain.Comment
 
public class Comment implements Serializable{
    private int id;
    private String content;
   // getter,setter
}

可以使用  <collection>  标签来配置一对一的关联映射,该标签含有的属性类似于 <association>:
  • property:必填,对应 POJO 中的属性名称;
  • ofType:集合元素的类型;
  • resultMap:可以通过该属性为集合元素直接使用现有的 resultMap;
  • columnPrefix:集合元素查询列的前缀,配置该属性后,在子标签配置 result 的 column 时可以设置该前缀值;
  • fetchType:抓取策略,可选值有 lazy(延迟抓取),eager(立即抓取);

以下是映射文件的一个示例的配置, mapper/UserMapper.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="site.assad.dao.UserDao">
    
    <!--User 的基本实体映射-->
    <resultMap id="userMap" type="site.assad.domain.User">
        <id property="id" column="user_id" />
        <result property="name" column="user_name" />
        <result property="email" column="user_email" />
    </resultMap>
    
    <!--User 一对多关联属性 commentList 的属性映射 -->
    <resultMap id="userCommentsMap" extends="userMap" type="site.assad.domain.User">
        <!--Comment 相关属性映射-->
        <collection property="comments" ofType="site.assad.domain.Comment" fetchType="lazy">
            <id property="id" column="comment_id" />
            <result property="content" column="comment_content"/>
        </collection>
    </resultMap>
    
    <!--示例一对多关联映射查询接口方法-->
    <select id="getUserByIdWithComments" resultMap="userCommentsMap">
        select u.user_id, u.user_name, u.user_email,
                c.comment_id, c.comment_content
        from user u
        inner join comments c on u.user_id = c.user_id
        where u.user_id = #{id}
    </select>
</mapper>

在Dao接口 site.assad.dao.UserDao 中定义接口方法:
 
public interface UserDao {
    User getUserByIdWithComments(int id);
}

以下是dao接口方法的测试代码:
 
public class UnitTest {
    private UserDao userDao;
    .....
    @Test
    public void testGetUserByIdWithComments(){
        User user  = userDao.getUserByIdWithComments(1);
        List<Comment> comments = user.getComments();
        comments.forEach(System.out::println);
    }
}




集成配置示例


以上的 POJO User 中同时含有一对一关联属性,一对多关联属性,如下:
site.assad.domain.User
 
public class User implements Serializable{
    private int id;
    private String name;
    private String email;
    private Role role;                     //一对一关系关联映射对象属性
    private List<Comment> comments;    //一对多的关联映射对象属性
    // getter,setter
}

可以使用以下比较简洁的 XML 配置方式, mapper/UserMapper.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="site.assad.dao.UserDao">
    
    <!--User 的基本实体映射-->
    <resultMap id="userMap" type="site.assad.domain.User">
        <id property="id" column="user_id" />
        <result property="name" column="user_name" />
        <result property="email" column="user_email" />
    </resultMap>
    
     <!--Role 的实体映射-->
    <resultMap id="roleMap" type="site.assad.domain.Role">
        <id property="id" column="role_id" />
        <result property="name" column="role_name" />
        <result property="group" column="role_group" />
    </resultMap>
    <!--Comment 的实体映射-->
    <resultMap id="commentMap" type="site.assad.domain.Comment">
        <id property="id" column="comment_id" />
        <result property="content" column="comment_content"/>
    </resultMap>
    <!--User 完整实体映射,包含两个关联属性的映射-->
    <resultMap id="userFullMap" type="site.assad.domain.User" extends="userMap">
        <association property="role" resultMap="roleMap" />
        <collection property="comments" resultMap="commentMap" fetchType="lazy"/>
    </resultMap>
    
    <!--查询接口方法配置-->
    <select id="getUserById" resultMap="userFullMap">
        select u.user_id, u.user_name, u.user_email,
        r.role_id, r.role_name, r.role_group,
        c.comment_id, c.comment_content
        from user u
        inner join role r on u.user_id = r.role_id
        inner join comments c on u.user_id = c.user_id
        where u.user_id = #{id}
    </select>
</mapper>
之后再在 site.assad.dao.UserDao 接口中添加接口方法: User getUserById(int id)  即可;



可以看到,以上的配置方式将 User、Role、Comment 的实体映射配置进一步独立处理,之后通过一个 resultMap 集成 userMap,并引用 roleMap,commentMap 的 resultMap 配置,这样的配置方式进一步提供了代码复用性;

在实际开发过程中,关于 Role,Comment 实体的配置往往不会编写在 UserMapper.xml ,而是编写在各自的实体映射 XML 中,如下:
mapper/RoleMapper.xml
 
<mapper namespace="site.assad.dao.RoleDao">
...
   <resultMap id="roleMap" type="site.assad.domain.Role">
        <id property="id" column="role_id" />
        <result property="name" column="role_name" />
        <result property="group" column="role_group" />
    </resultMap>
....
mapper/CommentMapper.xml
 
<mapper namespace="site.assad.dao.CommentDao">
....
    <resultMap id="commentMap" type="site.assad.domain.Comment">
        <id property="id" column="comment_id" />
        <result property="content" column="comment_content"/>
    </resultMap>
....
此时在 mapper/UserMapper.xml  可以跨文件通过相应的接口类引用这些 resultMap,而不用为一个 POJO 维护多个基本 resultMap,如下:
 
....
    <resultMap id="userMap" type="site.assad.domain.User">
        <id property="id" column="user_id" />
        <result property="name" column="user_name" />
        <result property="email" column="user_email" />
    </resultMap>
    <resultMap id="getUserFull" type="site.assad.domain.User" extends="userMap">
        <association property="role" resultMap="site.assad.dao.RoleDao.roleMap" />
        <collection property="comments" resultMap="site.assad.dao.CommentDao.commentMap"/>
    </resultMap>
....



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值