Mybatis的一对多(collection)和一对一(association)查询

Posted 构建巨人肩膀

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mybatis的一对多(collection)和一对一(association)查询相关的知识,希望对你有一定的参考价值。

1、mybatis支持映射复杂的查询结果集

2、表之间的关系

3、实体及其对应关系:

@Data
@EqualsAndHashCode(callSuper = false)
public class TestOne implements Serializable {
    private static final long serialVersionUID = 1L;
    private Integer id;    //
    private String nickname;    //
    private List<TestTwo> testTwos;
}
@Data
@EqualsAndHashCode(callSuper = false)
public class TestTwo implements Serializable {
    private static final long serialVersionUID = 1L;
    private Integer id;    //
    private String nickname;    //
    private Integer oneId;    //
    private TestOne testOne;
}

4、mybatis---------Association:  一对一查询的方式

<resultMap id="TestTwoAll" type="TestTwo">
        <id property="id" column="twoid"/>
        <result property="nickname" column="twonickname"/>
        <result property="oneId" column="one_id"/>
        <association property="testOne" column="one_id" javaType="TestOne">
            <id property="id" column="oneid"/>
            <result property="nickname" column="onenickname"/>
        </association>
    </resultMap>

    <select id="getTotalById" resultMap="TestTwoAll" parameterType="long">
        SELECT
        one.id as oneid,
        one.nickname as onenickname,
        two.id as twoid,
        two.nickname as twonickname,
        two.one_id
        FROM test_one one,test_two two
        where one.id=two.one_id and two.id=#{value}
    </select>

5、mybatis---------Collection:  一对多查询的方式

<resultMap id="TestOneAll" type="TestOne">
        <result property="id" column="oneid"/>
        <result property="nickname" column="onenickname"/>
        <collection property="testTwos" column="one_id" ofType="TestTwo" javaType="ArrayList">
            <result property="id" column="twoid"/>
            <result property="nickname" column="twonickname"/>
            <result property="oneId" column="one_id"/>
        </collection>
    </resultMap>

    <select id="getTotalById" resultMap="TestOneAll" parameterType="long">
        SELECT
        one.id as oneid,
        one.nickname as onenickname,
        two.id as twoid,
        two.nickname as twonickname,
        two.one_id
        FROM test_one one,test_two two
        where one.id=two.one_id and one.id=#{VALUE }
        order by twoid desc
    </select>

附录:

(1)建表语句:

CREATE TABLE `test_one` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `nickname` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;



CREATE TABLE `test_two` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `nickname` varchar(255) NOT NULL,
  `one_id` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `test_two_ibfk_1` (`one_id`),
  CONSTRAINT `test_two_ibfk_1` FOREIGN KEY (`one_id`) REFERENCES `test_one` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

(2)说明:(引自 http://blog.csdn.net/wxwzy738/article/details/24742495)

  1》

id, result元素

 

<id property="id" column="post_id"/>

<result property="subject" column="post_subject"/>

 

这是最基本的结果集映射。id 和result 将列映射到属性或简单的数据类型字段(String, int, double, Date等)。

这两者唯一不同的是,在比较对象实例时id 作为结果集的标识属性。这有助于提高总体性能,特别是应用缓存和嵌套结果映射的时候。

 

  2》

Association元素

 

<association property="author" column="blog_author_id" javaType=" Author">

<id property="id" column="author_id"/>

<result property="username" column="author_username"/>

</association>

Association元素处理“has-one”(一对一)这种类型关系。联合映射与其它的结果集映射工作方式差不多,指定property、column、javaType(通常MyBatis会自动识别)、jdbcType(如果需要)、typeHandler。

不同的地方是您需要告诉MyBatis 如何加载一个联合查询。MyBatis使用两种方式来加载:

·Nested Select:通过执行另一个返回预期复杂类型的映射SQL语句(即引用外部定义好的SQL语句块)。

·Nested Results:通过嵌套结果映射(nested result mappings)来处理联接结果集(joined results)的重复子集。

首先,让我们检查一下元素属性。正如您看到的,它不同于普通只有select和resultMap属性的结果映射。

Attribute

Description

property

映射数据库列的字段或属性。如果JavaBean 的属性与给定的名称匹配,就会使用匹配的名字。否则,MyBatis 将搜索给定名称的字段。两种情况下您都可以使用逗点的属性形式。比如,您可以映射到”username”,也可以映射到更复杂点的”address.street.number”。

column

数据库的列名或者列标签别名。与传递给resultSet.getString(columnName)的参数名称相同。

注意: 在处理组合键时,您可以使用column= “{prop1=col1,prop2=col2}”这样的语法,设置多个列名传入到嵌套查询语句。这就会把prop1和prop2设置到目标嵌套选择语句的参数对象中。

javaType

完整java类名或别名(参考上面的内置别名列表)。如果映射到一个JavaBean,那MyBatis 通常会自行检测到。然而,如果映射到一个HashMap,那您应该明确指定javaType 来确保所需行为。

jdbcType

支持的JDBC类型列表中列出的JDBC类型。这个属性只在insert,update 或delete 的时候针对允许空的列有用。JDBC 需要这项,但MyBatis 不需要。如果您直接编写JDBC代码,在允许为空值的情况下需要指定这个类型。

typeHandler

我们已经在文档中讨论过默认类型处理器。使用这个属性可以重写默认类型处理器。它的值可以是一个TypeHandler实现的完整类名,也可以是一个类型别名。

联合嵌套选择(Nested Select for Association)

select

通过这个属性,通过ID引用另一个加载复杂类型的映射语句。从指定列属性中返回的值,将作为参数设置给目标select 语句。表格下方将有一个例子。注意:在处理组合键时,您可以使用column=”{prop1=col1,prop2=col2}”这样的语法,设置多个列名传入到嵌套语句。这就会把prop1和prop2设置到目标嵌套语句的参数对象中。

  3》   

Collection元素 

<collection property="posts" ofType="domain.blog.Post">
<id property="id" column="post_id"/>
<result property="subject" column="post_subject"/>
<result property="body" column="post_body"/>
</collection>

collection元素的作用差不多和association元素的作用一样。事实上,它们非常相似,以至于再对相似点进行描述会显得冗余,因此我们只关注它们的不同点。

会像下面这样定义相应属性: 

private List<Post> posts;

映射一个嵌套结果集到一个列表,我们使用collection元素。就像association 元素那样,我们使用嵌套查询,或者从连接中嵌套结果集。 

<resultMap id=”blogResult” type=”Blog”>
<collection property="posts" javaType=”ArrayList” column="blog_id"
ofType="Post" select=”selectPostsForBlog”/>
</resultMap>

<select id=”selectBlog” parameterType=”int” resultMap=”blogResult”>
SELECT * FROM BLOG WHERE ID = #{id}
</select>

<select id=”selectPostsForBlog” parameterType=”int” resultType="Author">
SELECT * FROM POST WHERE BLOG_ID = #{id}
</select>

 

* 一看上去这有许多东西需要注意,但大部分看起与我们在association元素中学过的相似。首先,您会注意到我们使用了collection元素,然后会注意到一个新的属性“ofType”。这个元素是用来区别JavaBean属性(或者字段)类型和集合所包括的类型。因此您会读到下面这段代码。

 

<collection property="posts" javaType=”ArrayList” column="blog_id"

ofType="Post" select=”selectPostsForBlog”/>

理解为:“一个名为posts,类型为Post的ArrayList集合(A collection of posts in an ArrayList of type Post)” 。

javaType属性不是必须的,通常MyBatis 会自动识别,所以您通常可以简略地写成:

<collection property="posts" column="blog_id" ofType="Post"

select=”selectPostsForBlog”/>

 

以上是关于Mybatis的一对多(collection)和一对一(association)查询的主要内容,如果未能解决你的问题,请参考以下文章

Mybatis -- Mybatis多表查询:一对一(resultmapassociation匹配)一对多(collection集合)多对多(中间表)

mybatis-利用association和collection实现一对一和一对多

MyBatis关联查询,一对多关联查询

Mybatis 一对多分页踩坑 对collection的分析

MyBatis——关于一对多(<collection>)& 多对一(<association>)的案例详解

MyBatis——关于一对多(<collection>)& 多对一(<association>)的案例详解