有两个实体“人”和“地址”。人与地址之间存在1:M关系。 (假定某人有临时住所和永久住所)。
Person类的关键属性是:
Address类的关键属性是:
以下是Person和Address类的描述符代码片段:
public RelationalDescriptor buildPersonDescriptor() {
RelationalDescriptor descriptor = new RelationalDescriptor();
descriptor.setJavaClass(Person.class);
descriptor.addTableName("PERSON");
descriptor.addPrimaryKeyFieldName("PERSON.PID");
// RelationalDescriptor properties.
descriptor.useSoftCacheWeakIdentityMap();
descriptor.setIdentityMapSize(100);
descriptor.useRemoteSoftCacheWeakIdentityMap();
descriptor.setRemoteIdentityMapSize(100);
descriptor.setSequenceNumberFieldName("PERSON.PID");
descriptor.setSequenceNumberName("PERSON_SEQ");
descriptor.setAlias("person");
// Query manager.
descriptor.getDescriptorQueryManager().checkCacheForDoesExist();
descriptor.getDescriptorQueryManager().setAdditionalJoinExpression(new ExpressionBuilder().get("gender").equal('N'));
// Query manager.
// Mappings.
DirectToFieldMapping pIDMapping = new DirectToFieldMapping();
pIDMapping.setAttributeName("personId");
pIDMapping.setFieldName("PERSON.PID");
descriptor.addMapping(pIDMapping);
DirectToFieldMapping genderMapping = new DirectToFieldMapping();
genderMapping.setAttributeName("gender");
genderMapping.setFieldName("PERSON.GENDER");
descriptor.addMapping(genderMapping);
OneToManyMapping addressMapping = new OneToManyMapping();
addressMapping.setAttributeName("address");
addressMapping.setReferenceClass(Address.class);
addressMapping.useTransparentCollection();
addressMapping.useCollectionClass(IndirectList.class);
addressMapping.addTargetForeignKeyFieldName("ADDRESS.PID", "PERSON.PID");
descriptor.addMapping(addressMapping);
return descriptor;
}
public RelationalDescriptor buildAddressDescriptor() {
RelationalDescriptor descriptor = new RelationalDescriptor();
descriptor.setJavaClass(com.tropics.application.products.domain.costingandpricing.SellingPriceAddOn.class);
descriptor.addTableName("ADDRESS");
descriptor.addPrimaryKeyFieldName("ADDRESS.AID");
// Descriptor properties.
descriptor.useSoftCacheWeakIdentityMap();
descriptor.setIdentityMapSize(100);
descriptor.useRemoteSoftCacheWeakIdentityMap();
descriptor.setRemoteIdentityMapSize(100);
descriptor.setSequenceNumberFieldName("ADDRESS.AID");
descriptor.setSequenceNumberName("ADDRESS_SEQ");
descriptor.setAlias("address");
// Query manager.
descriptor.getDescriptorQueryManager().checkCacheForDoesExist();
//Mappings
DirectToFieldMapping genderMapping = new DirectToFieldMapping();
genderMapping.setAttributeName("gender");
genderMapping.setFieldName("ADDRESS.GENDER");
descriptor.addMapping(genderMapping);
DirectToFieldMapping personIDMapping = new DirectToFieldMapping();
personIDMapping.setAttributeName("personId");
personIDMapping.setFieldName("ADDRESS.PID");
descriptor.addMapping(personIDMapping);
DirectToFieldMapping addressIDMapping = new DirectToFieldMapping();
addressIDMapping.setAttributeName("addressId");
addressIDMapping.setFieldName("ADDRESS.AID");
descriptor.addMapping(addressIDMapping);
}
以下是用于生成动态查询的代码段:
ExpressionBuilder expBuilder = new ExpressionBuilder();
ReportQuery query = new ReportQuery(Person.class, expBuilder);
//Getting the MVSelling DetailsID and the number of Selling price add ons for each of them
query.addAttribute("personId", expBuilder.get("personId"));
query.addAttribute
("addressCounter", expBuilder.anyOfAllowingNone("address").get("addressId").count());
Expression addressExp = expBuilder.anyOfAllowingNone("address");
expBuilder.leftJoin(addressExp, addressExp.get("gender").equal('M'));
query.addNonFetchJoin(addressExp);
query.addGrouping("personId");
resultCollection = (Vector)clientSessionHolder.eclipselinkClientSession().executeQuery(query);
在运行该程序时,将根据日志生成查询:
SELECT t0.PID, COUNT(t1.AID)
FROM PERSON t0 LEFT OUTER JOIN ADDRESS t1
ON (t1.PID = t0.PID)
LEFT OUTER JOIN ADDRESS t2
ON ((t2.PID = t0.PID)
AND (t2.gender = 'M'))
WHERE (t0.gender = 'M')) GROUP BY t0.PID ;
如何编写在第一个连接子句本身中添加性别条件(db中的char数据类型)并摆脱第二个连接子句的表达式?
预期查询为: 选择t0.PID,COUNT(t1.AID) 来自人t0的左外连接地址t1 开启(t1.PID = t0.PID AND(t2.gender ='M')) t0.gender ='M'GROUP BY t0.PID
答案 0 :(得分:0)
您有两个单独的联接,因为要在表达式中调用并使用两次expBuilder.anyOfAllowingNone(“ address”)。 anyOfAllowingNone
告诉EclipseLink在该关系上创建一个外部联接,并将其用作以此为基础构建的表达式的基础。
尝试
Expression addressExp = expBuilder.anyOfAllowingNone("address");
query.addAttribute("addressCounter", addressExp.get("addressId").count());
expBuilder.leftJoin(addressExp, addressExp.get("gender").equal('M'));
query.addNonFetchJoin(addressExp);
重新使用addressExp将导致仅创建一次连接,并根据该连接建立其他路径,而不是新路径。