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

时间:2018-11-19 17:07:23

标签: eclipselink

有两个实体“人”和“地址”。人与地址之间存在1:M关系。 (假定某人有临时住所和永久住所)。

Person类的关键属性是:

  1. personId(pk)
  2. 性别

Address类的关键属性是:

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

以下是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

1 个答案:

答案 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将导致仅创建一次连接,并根据该连接建立其他路径,而不是新路径。