我正试图弄清楚如何使用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
}
@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 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());
仅使用值比较结果
这将返回预期值,但不使用定义比较,这只是目标的一半。
有没有办法在第二级深度查询定义及其字段?
答案 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的形式)。现在它就在那里,查询正在拉动预期的结果。