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