Java--Mybatis关联映射之关联单个对象(即一对一);关联多个对象(即一对多)

Posted MinggeQingchun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java--Mybatis关联映射之关联单个对象(即一对一);关联多个对象(即一对多)相关的知识,希望对你有一定的参考价值。

使用Mybatis框架,在业务需要对数据库进行关联查询的时候需使用关联映射
而关联映射分为关联单个对象与关联多个对象,即一对一、一对多的情况,且每种关联方式都可以有两种处理情况,即使用1条sql进行处理与使用2条sql进行处理

已有表关系如下(表的字段名与实体类中的属性名一致):
user表:主键为user_Id
book表:主键为book_id

Java实体类对象如下:
1、domain.User.java

package domain;
import java.util.List;

public class User {
    private String user_id;//用户id,主键
    private String user_name;//用户姓名
    private String user_password;//用户密码
    private List<Book> books;//用户拥有的书籍信息,用户与书籍是一对多的关系

    public List<Book> getBooks() {
        return books;
    }
    public void setBooks(List<Book> books) {
        this.books = books;
    }
    public String getUser_id() {
        return user_id;
    }
    public void setUser_id(String user_id) {
        this.user_id = user_id;
    }
    public String getUser_name() {
        return user_name;
    }
    public void setUser_name(String user_name) {
        this.user_name = user_name;
    }
    public String getUser_password() {
        return user_password;
    }
    public void setUser_password(String user_password) {
        this.user_password = user_password;
    }
    @Override
    public String toString() {
        return "User [user_id=" + user_id + ", user_name=" + user_name + ", user_password="
                + user_password + ", books=" + books + "]";
    }
}

2、domain.Book.java

package domain;

public class Book {
    private String book_id;//书籍id,主键
    private String user_id;//所属用户id,外键参照于用户表的主键
    private String book_name;//书籍名称
    private User user;//书籍所属用户关系,书籍与用户为一对一

    public String getBook_id() {
        return book_id;
    }
    public void setBook_id(String book_id) {
        this.book_id = book_id;
    }
    public String getUser_id() {
        return user_id;
    }
    public void setUser_id(String user_id) {
        this.user_id = user_id;
    }
    public String getBook_name() {
        return book_name;
    }
    public void setBook_name(String book_name) {
        this.book_name = book_name;
    }
    public User getUser() {
        return user;
    }
    public void setUser(User user) {
        this.user = user;
    }
    @Override
    public String toString() {
        return "Book [book_id=" + book_id + ", user_id=" + user_id + ", book_name=" + book_name
                + ", user=" + user + "]";
    }
}

3、mapper.BookAndUserMapper(Mapper映射器) 

package mapper;
import java.util.List;
import domain.Book;

public interface UserMapper {
	//关联单个对象
	public List<Book> findBookAndUser1();//一条语句执行sql
	public List<Book> findBookAndUser2();//两条语句执行sql


    //关联多个对象
	public User findUserById1(String userId);//一条语句执行sql
	public User findUserById2(String userId);//两条语句执行sql
}

4、UserMapper.xml 

一、一对一,<association>标签

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN"
        "http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd">

<!-- namespace为命名空间,需与映射器全名一致 -->
<mapper namespace="mapper.UserMapper">
    <!--使用一条sql语句来加载Book和关联的User(使用内连接)-->
    <select id="findBookAndUser1" resultMap="bookMap1" >
        SELECT * FROM book 
        LEFT JOIN user ON book.user_id = user.user_id
    </select>
    <!--书籍关联查询结果映射-->
    <resultMap id="bookMap1" type="domain.Book">
        <!-- id指定主键,其余字段用result指定 -->
        <id property="book_id" column="book_id"></id>
        <result property="user_id" column="user_id"></result>
        <result property="book_name" column="book_name"></result>
        <!--映射关系,指定属性与属性的类型-->
        <association property="user" javaType="domain.User">
            <id property="user_id" column="user_id"></id>
            <result property="user_name" column="user_name"></result>
            <result property="user_password" column="user_password"></result>
        </association>
    </resultMap>


    <!-- 使用两条sql语句来加载Book和关联的User(关联单个对象) -->
    <select id="findBookAndUser2" resultMap="bookMap2">
        select *from book
    </select>
    <resultMap id="bookMap2" type="domain.Book">
        <association property="user" javaType="domain.User" select="findUser"
                     column="user_id"></association>
    </resultMap>
    <!-- 此处id必须与上面一致 -->
    <select id="findUser" parameterType="String" resultType="domain.User">
        select *from user where user_id = #{userId}
    </select>
</mapper>

二、一对多,<collection>标签

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN"
        "http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd">

<!-- namespace为命名空间,需与映射器全名一致 -->
<mapper namespace="mapper.UserMapper">
    <!-- 使用一条sql语句来加载User和关联的Book(关联多个对象) -->
    <select id="findUserById1" parameterType="String" resultMap="userMap1">
        select * from user u 
        left join book b on (u.user_id = b.user_id)
        where u.user_id = #{userId}
    </select>
    <resultMap id="userMap1" type="domain.User">
        <!-- 定义user字段的装载,一定不能少写 -->
        <id property="user_id" column="user_id" />
        <result property="user_name" column="user_name" />
        <result property="user_password" column="user_password" />
        <collection property="books" javaType="java.util.List" ofType="domain.Book">
            <id property="book_id" column="book_id" />
            <result property="user_id" column="user_id" />
            <result property="book_name" column="book_name" />
        </collection>
    </resultMap>


    <!-- 使用两条sql语句来加载User和关联的Book(关联多个对象) -->
    <select id="findUserById2" parameterType="String" resultMap="userMap2">
        select * from user 
        where user_id = #{userId}
    </select>
    <resultMap id="userMap2" type="domain.User">
        <!-- 映射主键 -->
        <id property="user_id" column="user_id"/>
        <!-- 映射其他字段,此处可以选择性指定其他属性 -->
        <result property="user_name" column="user_name"/>
        <!-- 指定books属性是一个List<Book>集合 -->
        <collection property="books" javaType="java.util.List" ofType="domain.Book"
                    select="findBooks" column="user_id" >
        </collection>
    </resultMap>
    <select id="findBooks" parameterType="String" resultType="domain.Book">
        select * from book 
        where user_id = #{userId}
    </select>
</mapper>

《阿里巴巴JAVA开发手册》里面写超过三张表禁止join,原文如下:

此规范是针对mysql系数据库的,模拟一些场景多造些数据去查询对比不难发现:每增加1张表的JOIN,查询性能就会显著下降

因此我们还是要根据业务场景去灵活运用 

针对阿里为何这样规定,以及如何解决,可参考文章

《阿里巴巴JAVA开发手册》超过三张表禁止join

以上是关于Java--Mybatis关联映射之关联单个对象(即一对一);关联多个对象(即一对多)的主要内容,如果未能解决你的问题,请参考以下文章

hibernate之关联映射

mybatis xml数据层框架应用--Mybatis关系映射之一对多关系映射

mybatis xml数据层框架应用--Mybatis关系映射之一对一关系映射

mybatis中的ResultMap关联映射

Android ORM对象关系映射之GreenDAO建立多表关联

HIbernate学习笔记4 之 延迟加载和 关联映射