Eclipselink 左外连接动态查询格式错误

Eclipselink left outer join dynamic query malformed

有两个实体 Person 和 Address。从 Person 到 Address 存在 1:M 关系。 (假设一个人有临时地址和永久地址)。

Person class 的关键属性是:

  1. personId(pk)
  2. 性别

Address class 的关键属性是:

  1. addressId(pk)
  2. personId(fk)
  3. 性别

以下是 Person 和 Address classes 的描述符代码片段:

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 数据类型)并摆脱第二个连接子句?

预期的查询是: SELECT t0.PID, 计数(t1.AID) FROM PERSON t0 左外连接地址 t1 打开(t1.PID = t0.PID 和(t2.gender = 'M')) 其中 t0.gender = 'M' 按 t0.PID

分组

您有两个单独的联接,因为您在表达式中调用并使用了 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 将导致仅创建一次连接,并根据它构建其他路径而不是新路径。