如何使用DataNucleus JDOQL API在Collection中查询对象?

时间:2015-04-07 15:30:44

标签: java mysql datanucleus jdoql

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

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

我想检查ObjectAttribute是否存在,其值字段与指定的值对齐,其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
}

ObjectAttribute

@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;
        }
    }
}

ObjectAttributeDefinition

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 Specification似乎意味着,一切都应该像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());

仅使用值比较结果

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

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

1 个答案:

答案 0 :(得分: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的形式)。现在它就在那里,查询正在拉动预期的结果。