在mybatis条件查询中进行类关联查询(类Hibernate关联查询)

上一篇中,已经解决了如何使用构建条件进行数据查询。但在常规的查询中,并不总是单独查询某一个表信息,某些条件还需要关联其它数据表才能得出。我们希望在进行查询时,能够根据条件中所指定的关联表进行关联化查询,并在条件中自动处理关联化条件。如下的查询语句所示:

select a.* from tableA a inner join tableB b on b.a_id = a.id where b.c_id = ? and b.d = ? and a.e != ? 

那么在相应的条件中,即要处理模型之间的关联关系,同时处理在条件中的前缀别名信息,以保证所在表的正确性。那么相应的Criteria表达应该如下所示:

List<Criteria> criteriaList = Lists.newArrayList();
criteriaList.add(Criterias.link(B.class, "b", "aId", LinkMode.INNER));
criteriaList.add(Criterias.eq("b.c_id", cId));
criteriaList.add(Criterias.eq("b.d", d));

即在原来的基础之上,增加一个用于描述关联关系的LinkCriteria,同时在相应的条件上增加属性前缀,用于描述指定的条件主体(当然如果是当前主体不需要前缀)。在具体的生成Mql的过程当中,增加用于处理关联关系的逻辑,同时处理条件的前缀即可。

1    关联关系条件LinkCriteria

在关联式条件中,相应的关联语句应该如以下所示:

inner(关联类型) join tableB(目标表) b(目标表别名) on b.a_id(目标表字段名) = a(原表别名).id(原表字段名)

针对相应的调用方式

方式A:Criterias.link(B.class, "b", "aId", LinkMode.INNER)
方式B:link(B.class, "b", "aId",A.class, "id", LinkMode.INNER)

可以知道,在实现层面,只需要针对相应的属性作简单的拼装即可。
在方式A的处理中,我们默认与root表(即原表)进行关联,关联的两个表的字段均为a_id,关联类型为内联结。
而方式B,则完成对相应的关联语句进行细化,完全重现相应的关联元素信息。

在这里,我们引入了一个新的元素,表别名,用于描述在整个SQL语句中,不同表的字段区分。为了与旧逻辑兼容,当未提供别名时,默认为root表(其别名为root_),具体实现参考如下:

		Table destTable = 目标表;
		ColumnMapping destColumnMapping = 目标字段映射信息;
		ColumnMapping selfColumnMapping = 原表字段映射信息;

		//产生 inner join tableA a on a.xxx = b.yyy
		StringBuilder builder = new StringBuilder();
		builder.append(linkMode.symbol()).append(" join ")// inner/outer join
				.append(destTable.schema()).append(".").append(destTable.name()).append(" ")
				.append(destAlias)// tableA a
				.append(" on ")//on
				.append(destAlias).append(".").append(destColumnMapping.getJdbcField())// a.xxx
				.append(" = ")//=
				.append(selfAlias).append(".").append(selfColumnMapping.getJdbcField());// b.yyy
		return new Mll(destClass, destAlias, builder.toString());

2    属性前缀(表别名)

由于增加了新的表别名,在处理相应的属性时,将自动对相应的属性进行拆分。即将表别名与属性值进行拆分成表别名.属性的样式。如针对属性b.aId,将表示为模型b的属性aId。这个拆分很简单,直接以.分隔即可。当不存在前缀时,使用默认前缀即可。

在拆分之后,为了保证获取的属性在正确的模型中,就需要根据别名查找相应的模型了。这个逻辑也只需要将关联关系预先处理,同时将模型和别名关系进行映射,那么在之后的处理中即可根据别名和属性找到正确的映射了。

3    集成处理

在整个操作完成之后,我们即产生了相应的完整处理步骤,如下所示

1 处理关联关系
2 处理条件,并引入别名机制
3 联合拼接,并进行处理

那么,相应的mql生成语句则可如下所示:

select *(或者特定属性)
		from ${table.schema()}.${table.name()} root_
//这里为处理关联条件
		<foreach collection="mllList" item="mll" separator=" ">
			${mll}
		</foreach>
//处理查询条件
		<if test="mqlList.size > 0">
			where
			<foreach collection="mqlList" item="mql" separator="and">
				${mql}
			</foreach>
		</if>

转载请标明出处:i flym
本文地址:https://www.iflym.com/index.php/code/201312250003.html

相关文章:

作者: flym

I am flym,the master of the site:)

发表评论

邮箱地址不会被公开。 必填项已用*标注