我有这样的实体,使用GORM存储在数据库中(我省略了不相关的字段):
public class JsonParser {
public static List<DrawerItem> parseFeed(String content) {
try {
JSONObject jsonRootObject = new JSONObject(content);
JSONArray jsonArray = jsonRootObject.optJSONArray("Rows");
List<DrawerItem> draweritemList = new ArrayList<>();
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject obj = jsonArray.getJSONObject(i);
DrawerItem draweritem = new DrawerItem();
draweritem.setId(obj.getString("Id"));
draweritem.setTitle(obj.getString("Title"));
draweritemList.add(draweritem);
}
return draweritemList;
} catch (JSONException e) {
e.printStackTrace();
return null;
}
}
}
所以我们在顶部有付款,可以有很多PaymentEnies,每个PaymentEntry都可以属于一个PaymentCategory。
我需要选择符合某些条件的付款,但只需选择也属于特定类别的付款条款的付款。目前我在3个查询中执行此操作:
选择适合类别名称部分的类别,或者只是省略类别查询(在这种情况下,我们希望所有付款,无论其条目类别如何):
class Payment {
static hasMany = [paymentEntries: PaymentEntry]
}
class PaymentEntry {
static hasOne = [category: PaymentCategory]
static belongsTo = [payment: Payment]
static constraints = {
category(nullable: true)
}
}
class PaymentCategory {
static hasMany = [payments: PaymentEntry, rules: PaymentRule]
String name
}
根据PaymentCategory选择PaymentEntries ID:
private static List<PaymentCategory> getCategories(String category) {
def result = null
if (category != null && category.length() > 0) {
def c = PaymentCategory.createCriteria()
result = c {
ilike("name", "%${category}%")
}
}
result
}
最后选择付款,仅限于包含特定PaymentEntries的付款:
private static List<Long> paymentEntryIds(String category) {
def categories = getCategories(category)
def c = PaymentEntry.createCriteria()
def result = new ArrayList()
// If category is selected, but there is no matching category, return empty list
if (!categorySelectedButNoMatch(category, categories)) {
result = c {
if (category == null) {
isNull("category")
} else if (categories != null && categories.size() > 0) {
inList("category", categories)
}
projections {
property("id")
}
}
}
result
}
这样可行,但它会对数据库运行3次查询。我非常确定这段代码可以更干净,而且可以在更少的查询中完成。关于如何改进它的所有想法都是受欢迎的。
答案 0 :(得分:0)
您可以使用至少3种不同的方法:分离查询,查询和HQL子查询的子查询。
带有条件的DetachedQuery示例如下:
def subquery = new DetachedCriteria(PaymentCategory).build {
projections {
groupProperty 'id'
}
ilike("name", "%${category}%")
}
然后您可以在另一个查询中使用此子查询:
return PaymentEntry.createCriteria().list {
category {
inList "id", subquery
}
}
我没有在你的域名上测试它,这应该只是表明这个想法。请参阅GORM文档的DetachedCriteria部分:https://grails.github.io/grails-doc/latest/guide/single.html#detachedCriteria
我们将它用于一些非常复杂的查询。有时候createAlias
需要正确使用关联。