Создать критерии в Grails с учетом отношения hasMany

у меня два класса

Quiz{
  String name
  static hasMany[tags:Tag]
}

Tag{
    String tag
}

Как я могу написать следующий запрос в Grails, используя построитель критериев

select count(tag_id),tag  from quiz_tag 
left outer join tag on tag_id=id
group by tag_id,tag

person Sap    schedule 05.10.2012    source источник


Ответы (3)


Вы можете сделать это с помощью запроса критериев, если сопоставите таблицу «многие ко многим» с классом предметной области, как описано здесь.

class QuizTag {
    Quiz quiz
    Tag tag

    ...
}

def counts = QuizTag.withCriteria {
    projections {
        groupProperty('tag')
        rowCount()
    }
}

Переменная counts будет List из [Tag object, count of the Tag] списков.

person schmolly159    schedule 06.10.2012
comment
Он schmolly, я пытался сделать это, но я получаю эту ошибку NULL не допускается для столбца QUIZ_ID; Оператор SQL: вставить в quiz_tag (id, version, date_created, last_updated, tag_id, quiz_id, tags_idx) значения (null, ?, ?, ?, ?, ?, ?) [23502-164] Есть идеи? У меня есть hasMany = [quizTags:quizTag] - person Sap; 08.10.2012
comment
Можете ли вы поверить, что я исправил это через несколько минут после того, как опубликовал последнее сообщение :) - person Sap; 08.10.2012
comment
Эй, Шмолли, я пытался сделать именно то, что вы здесь сказали, но теперь я получаю сообщение об ошибке где-то еще в моем коде! не могли бы вы взглянуть на мой другой вопрос, на всякий случай, если у вас есть ответ? stackoverflow.com/questions/12808800/ - person Sap; 11.10.2012

Кажется, вы хотите узнать, сколько раз каждый тег используется в викторинах. Определив свои доменные классы, как вы это сделали, вы получили среднюю таблицу quiz_tag, и с помощью строки SQL вы можете узнать результат на этот вопрос.

Но кажется, что это невозможно с critera builder, то есть Hibernate, потому что из Tag вы не можете получить доступ к присоединяемой таблице. Вы можете сделать это из викторины, потому что в викторине есть hasMany[tags:Tag]

Вы можете получить доступ к объединенной таблице из тега, если измените ее следующим образом:

Tag{
    String tag

    static belongsTo = Quiz
    static hasMany[quizes:Quiz]
  }

Ваша модель базы данных остается прежней, но теперь Hibernate может перейти от тега к присоединенной таблице. Вы можете попробовать этот запрос HQL, который даст вам тег и количество вхождений в викторинах:

Tag.executeQuery("SELECT t, count(q) FROM Tag t JOIN FETCH t.quizes q GROUP BY t")

Я думаю, что проще просто с HQL, но я думаю, вы могли бы сделать это и с построителем критериев, возможно, используя sqlGroupProjection для группировки, если он поддерживается.

person MBozic    schedule 05.10.2012
comment
Есть ли шанс, что вы знаете, как это сделать с критериямиBuilder? Единственная причина в том, что HQL не поддерживается во многих хранилищах данных, в основном NoSql. Я не уверен, будет ли поддерживаться CriterionBuilder или нет, но шансы выше! Кстати, вы правы в отношении цели запроса, так же, как и SO, я хочу иметь возможность показать, какой тег используется чаще всего, и отображать его в порядке популярности. - person Sap; 05.10.2012
comment
Я получаю это исключение, если пытаюсь использовать предложенное вами отношение. Владелец не определен между классами домена [класс com.easytha.Quiz] и [класс com.easytha.Tag] в отношениях «многие ко многим». Пример: static createdTo = com.easytha.Tag -›› - person Sap; 06.10.2012

У меня была аналогичная проблема, когда у клиентов было одно или несколько ассоциаций с магазинами. Можно было использовать критерии для подсчета магазинов, используя следующий код.

class Customer {
    static hasMany = [stores : Store]
    ... 
}

class Store {
    Customer customer
    ...
}

def c = Store.createCriteria()
def results = c.list {
    customer {
        'in'("customerNumber",['1-1','1-2','1-3'])
    }
    projections {
        sqlGroupProjection 'customer_id, count(customer_id) as numberOfStores', 'customer_id', ['customer_id', 'numberOfStores'], [INTEGER, INTEGER]
    }
}

Результат: [[1, 3], [2, 3]]

Где возвращаемые поля: [customer.id, numberOfStores]

person Daniel Bjuhr    schedule 17.09.2014