0

我试图弄清楚如何使用 RDBMS 和 DataNucleus 查询持久对象集合中的对象。我有一个用户、一个 ObjectAttribute 和一个 ObjectAttributeDefinition。

User 可能有多个 ObjectAttribute,每个 ObjectAttribute 都有一个 ObjectAttributeDefinition。这个想法是一些定义可以定义一大堆 ObjectAttributes。

我想检查是否存在一个 ObjectAttribute,其 value 字段与指定的字段对齐,并且其 ObjectAttributeDefinition 包含字段 attributeName,其值设置为我指定的 attributeName。

换句话说:

for (ObjectAttribute attribute : userAttributeCollection)
{
    if(attribute.value == myValue && attribute.definition.attributeName == myName)
        return success;
}

我有以下三个课程:

用户

@Component
@PersistenceCapable
public class User implements Serializable
{
    @Persistent(table="USER_ATTRIBUTES")
    @Join(column="USER_ID")
    @Element(column = "ATTRIBUTE_ID")
    private List<ObjectAttribute> userAttributeCollection;

    ///... Constructors, getters and setters, Primary Key definition below
}

对象属性

@Component
@PersistenceCapable
public class ObjectAttribute implements Serializable
{
    @Persistent(table="ATTRIBUTE_DEFINITION_JOIN")
    @Join(column="ATTRIBUTE_ID")
    @Element(column="DEFINITION_ID")
    private ObjectAttributeDefinition definition;
    private String value;

    //...

    @Override
    public boolean equals(Object obj)
    {
        ObjectAttribute testObject = (ObjectAttribute) obj;
        if (this.value.equals(testObject.getValue()) && this.definition.getAttributeName().equals(testObject.getDefinition().getAttributeName())) {
            return true;
        }
        else {
            return false;
        }
    }
}

对象属性定义

public class ObjectAttributeDefinition implements Serializable
{
    public enum ATTRIBUTE_NAMES
    {
        //Google Search Page Attribute (https://cloud.google.com/appengine/docs/java/search/)
        SEARCH_PAGE("SEARCH_PAGE");

        private final String text;

        ATTRIBUTE_NAMES(String type)
        {
            this.text = type;
        }

        @Override
        public String toString()
        {
            return text;
        }
    }

    private ATTRIBUTE_NAMES attributeName;

    //...

    @Override
    public boolean equals(Object obj)
    {
        ObjectAttributeDefinition definition = (ObjectAttributeDefinition) obj;
        return this.attributeName.equals(definition.attributeName);
    }

}

进一步说明

我有一个 DAO 类和为访问这些持久对象定义的方法列表。整个基础设施似乎设置正确,因为持久化对象并再次检索它们似乎工作正常。

我确保对象属性唯一性的方法是查询 ObjectAttribute 的值和 ObjectAttributeDefinition 的名称。

我试过的

基本查询

        Query query = pm.newQuery(User.class, "userAttributeCollection.contains(att) & att.value == :val & att.definition.attributeName == :def");
        query.declareVariables("ObjectAttribute att");
        query.declareImports("import com.us.orm.general.models.ObjectAttributeDefinition; import com.us.orm.general.models.ObjectAttribute");

        query.setResultClass(User.class);

        rval =  (List<User>) query.execute(myAtt.getValue(), myAtt.getDefinition().getAttributeName());

基本查询错误

Query has reference to member "attributeName" of class "com.us.orm.general.models.ObjectAttribute" yet this doesnt exist!

正如JDO 规范似乎暗示的那样,一切都应该非常类似于 Java。但是,由于某种原因,我似乎无法访问低于第一层的对象。

所以我试图破解比较。

在 ObjectAttribute 中使用 equals() 覆盖

        Query query = pm.newQuery(User.class, "userAttributeCollection.contains(att) & att == :val");
        query.declareVariables("ObjectAttribute att");
        query.declareImports("import com.us.orm.general.models.ObjectAttributeDefinition; import com.us.orm.general.models.ObjectAttribute");

        query.setResultClass(User.class);

        rval =  (List<User>) query.execute(myAtt);

在 ObjectAttribute 结果中使用 equals() 覆盖

我收到零结果。查看为该对象生成的实际 SQL,我得到以下信息:

SELECT DISTINCT 'com.us.orm.user.models.User' AS NUCLEUS_TYPE,`A0`.`CREATED`,`A0`.`EMAIL`,`A0`.`FIRSTNAME`,`A0`.`ISACTIVE`,`A0`.`LASTMODIFIED`,`A0`.`LASTNAME`,`A0`.`PASSWORD`,`A0`.`PROFILEBANNERBUCKET`,`A0`.`PROFILEBANNERFILENAME`,`A0`.`PROFILEIMAGEBUCKET`,`A0`.`PROFILEIMAGEFILENAME`,`A0`.`USERID`,`A0`.`USERNAME` FROM `USER` `A0` INNER JOIN `USER_ATTRIBUTES` `B0` ON `A0`.`USERID` = `B0`.`USER_ID` INNER JOIN `OBJECTATTRIBUTE` `C0` ON `B0`.`ATTRIBUTE_ID` = `C0`.`ATTRIBUTEID` WHERE `C0`.`ATTRIBUTEID` = null

检查空引用的 ATTRIBUTEID 永远不会返回结果。所以这是我的代码与 DataNucleus 的接口一侧,但我又不知所措了。

也许我可以在 ObjectAttribute 和 ObjectAttributeDefinition 上覆盖 equals() ..

等于覆盖 ObjectAttribute 和 ObjectAttributeDefinition

    Query query = pm.newQuery(User.class, "userAttributeCollection.contains(att) & att.value == :val & att.definition == :def");
    query.declareVariables("ObjectAttribute att");
    query.declareImports("import com.up.orm.general.models.ObjectAttributeDefinition; import com.up.orm.general.models.ObjectAttribute");

    query.setResultClass(User.class);

    rval =  (List<User>) query.execute(myAtt.getValue(), myAtt.getDefinition());

等于覆盖 ObjectAttribute 和 ObjectAttributeDefinition 结果

rval 返回 null,不生成数据库查询,也不抛出异常。

仅使用值比较

        Query query = pm.newQuery(User.class, "userAttributeCollection.contains(att) & att.value == :val");
        query.declareVariables("ObjectAttribute att");
        query.declareImports("import com.up.orm.general.models.ObjectAttributeDefinition; import com.up.orm.general.models.ObjectAttribute");

        query.setResultClass(User.class);

        rval =  (List<User>) query.execute(myAtt.getValue());

仅使用值比较结果

这将返回预期值,但不使用定义比较,这只是目标的一半。

有没有办法在第二层深度查询定义及其字段?

4

1 回答 1

0

我已经想出了解决方案。我可能在文档中错过了这一点,但我不知道声明的变量实际上在 SQL 中执行“交叉连接”。这是解决问题的一个非常重要的方面。

查询如下:

    Query query = pm.newQuery(User.class, "userAttributeCollection.contains(att) & att.value == :val & definition.attributeName == :name");
    query.declareVariables("ObjectAttribute att; ObjectAttributeDefinition definition");
    query.declareImports("import com.us.orm.general.models.ObjectAttributeDefinition; import com.us.orm.general.models.ObjectAttribute");

    query.setResultClass(User.class);

    rval =  (List<User>) query.execute(myAtt.getValue(), name.toString());

我错过了过滤器的“交叉连接”变量片段(以 ObjectAttributeDefinition 的形式)。现在它在那里,查询正在提取预期的结果。

于 2015-04-08T18:51:03.903 回答