mybatis —— <association>关联的结果查询

接下来的文章中,关于Mybatis的示例,全部来自于Mybatis代码中的单元测试代码,通过这些代码能够学习Mybatis中很有用的知识,这些内容在doc文档中可能只是简单提到了,或者有一些文字说明,通过这些单元测试能更直观的了解如何在Mybatis使用这些内容。


这一节内容为Association关联的结果查询,就是在查询出结果后,根据查询的列和resultMap定义的对应关系,来创建对象并写入值。

  • association – 一个复杂的类型关联;许多结果将包成这种类型
    • 嵌入结果映射 – 结果映射自身的关联,或者参考一个

(注:“参考一个”,这里参考一个是通过对象的Key来唯一确定的,如果Key值一样,就直接用已经存在的这个对象。)


association是resultMap中的一个配置选项,下面是用到的类的UML图:



Car对象中包含了Engine和Brakes两个对象。Mapper是接口对象。AssociationTest是该测试对象。

drop table cars if exists;

create table cars (
  carid integer,
  cartype varchar(20),
  enginetype varchar(20),
  enginecylinders integer,
  brakestype varchar(20)
);

insert into cars (carid, cartype, enginetype, enginecylinders, brakestype) values(1, 'VW',   'Diesel', 4,    null);
insert into cars (carid, cartype, enginetype, enginecylinders, brakestype) values(2, 'Opel',    null,    null, 'drum');
insert into cars (carid, cartype, enginetype, enginecylinders, brakestype) values(3, 'Audi', 'Diesel', 4,    'disk');
insert into cars (carid, cartype, enginetype, enginecylinders, brakestype) values(4, 'Ford', 'Gas',    8,    'drum');

Mapper.xml文件:

<mapper namespace="org.apache.ibatis.submitted.associationtest.Mapper">
	<resultMap type="org.apache.ibatis.submitted.associationtest.Car" id="carResult">
		<id column="carid" property="id"/>
		<result column="cartype" property="type"/>
		<association property="engine" resultMap="engineResult"/>
		<association property="brakes" resultMap="brakesResult"/>
	</resultMap>
	<resultMap type="org.apache.ibatis.submitted.associationtest.Engine" id="engineResult">
		<result column="enginetype" property="type"/>
		<result column="enginecylinders" property="cylinders"/>
	</resultMap>
	<resultMap type="org.apache.ibatis.submitted.associationtest.Brakes" id="brakesResult">
		<result column="brakesType" property="type"/>
	</resultMap>
	<select id="getCars" resultMap="carResult">
		select * from cars
	</select>
	<select id="getCarsNonUnique" resultMap="carResult">
		select 1 as carid, cartype, enginetype, enginecylinders, brakestype from cars
	</select>
	<select id="getCars2" resultMap="carResult">
		select 1 as carid, cartype, enginetype, enginecylinders, brakestype from cars where carid in (1,2)
	</select>
</mapper>

其中的一个测试用例:

@Test
public void shouldGetAllCars() {
    SqlSession sqlSession = sqlSessionFactory.openSession();
    try {
        Mapper mapper = sqlSession.getMapper(Mapper.class);
        List<Car> cars = mapper.getCars();
        Assert.assertEquals(4, cars.size());
        Assert.assertEquals("VW", cars.get(0).getType());
        Assert.assertNotNull(cars.get(0).getEngine());
        Assert.assertNull(cars.get(0).getBrakes());
        Assert.assertEquals("Opel", cars.get(1).getType());
        Assert.assertNull(cars.get(1).getEngine());
        Assert.assertNotNull(cars.get(1).getBrakes());
    } finally {
        sqlSession.close();
    }
}

cars返回值:



association是嵌套查询中最简单的一种情况,像上述例子中,一般我们都会用一个Car对面包含所有的属性,这里的例子使用了嵌套对象,使对像的结构更鲜明。不过一般情况下很少会拆分一个对象为多个,用的多的时候是多表查询的嵌套。


上面XML中的carResult和engieResult,brakesResult都是分别定义,carResult引用了另外两个resultMap。对于不需要重用嵌套对象的情况,还可以直接这么写,把上面的XML修改后:

<resultMap type="org.apache.ibatis.submitted.associationtest.Car" id="carResult">
	<id column="carid" property="id"/>
    <result column="cartype" property="type"/>
    <association property="engine" javaType="org.apache.ibatis.submitted.associationtest.Engine">
		<result column="enginetype" property="type"/>
        <result column="enginecylinders" property="cylinders"/>
    </association>
    <association property="brakes" resultMap="brakesResult"/>
</resultMap>

为了对比和区分,这里指修改了Engine,在association元素上增加了属性javaType,元素内增加了result映射。


--------------------------------------------------复杂映射---------------------------------------------

<!-- Very Complex Result Map -->
<resultMap id="detailedBlogResultMap" type="Blog">
	<constructor>
		<idArg column="blog_id" javaType="int"/>
	</constructor>
	<result property="title" column="blog_title"/>
	<association property="author" column="blog_author_id" javaType="Author">
		<id property="id" column="author_id"/>
		<result property="username" column="author_username"/>
		<result property="password" column="author_password"/>
		<result property="email" column="author_email"/>
		<result property="bio" column="author_bio"/>
		<result property="favouriteSection" column="author_favourite_section"/>
	</association>
	<collection property="posts" ofType="Post">
		<id property="id" column="post_id"/>
		<result property="subject" column="post_subject"/>
		<association property="author" column="post_author_id" javaType="Author"/>
		<collection property="comments" column="post_id" ofType=" Comment">
			<id property="id" column="comment_id"/>
		</collection>
		<collection property="tags" column="post_id" ofType=" Tag" >
			<id property="id" column="tag_id"/>
		</collection>
		<discriminator javaType="int" column="draft">
			<case value="1" resultType="DraftPost"/>
		</discriminator>
	</collection>
</resultMap>

resultMap 元素有很多子元素和一个值得讨论的结构。下面是 resultMap 元素的概念视图

resultMap

    constructor – 类在实例化时,用来注入结果到构造方法中

    idArg – ID 参数;标记结果作为 ID 可以帮助提高整体效能

    arg – 注入到构造方法的一个普通结果

    id – 一个 ID 结果;标记结果作为 ID 可以帮助提高整体效能

    result – 注入到字段或 JavaBean 属性的普通结果

    association – 一个复杂的类型关联;许多结果将包成这种类型

        嵌入结果映射 – 结果映射自身的关联,或者参考一个

    collection – 复杂类型的集

        嵌入结果映射 – 结果映射自身的集,或者参考一个

    discriminator – 使用结果值来决定使用哪个结果映射

    case – 基于某些值的结果映射

        嵌入结果映射 – 这种情形结果也映射它本身,因此可以包含很多相同的元素,或者它可以参照一个外部的结果映射。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值