2013-04-19 1 views
1

В проекте есть код. Я работаю над тем, где динамический искатель ведет себя по-разному в одной ветви кода, чем в другом.Может ли динамический искатель Grails сломаться кодом приложения?

Эта строка кода возвращает все мои рекламодатели (есть 8 из них), независимо от того, какой отрасли я нахожусь в.

Advertiser.findAllByOwner(ownerInstance) 

Но когда я начинаю добавлять условия, все становится странно. В ветви А, следующий код возвращает все мои рекламодателями:

Advertiser.findAllByOwner(ownerInstance, [max: 25]) 

Но в ветви В, этот код возвращает только 1 рекламодатель.

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

Редактировать

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

static mapping = { 
    owner fetch: 'join' 
    category fetch: 'join' 
    subcategory fetch: 'join' 
} 

static fetchMode = [ 
     grades: 'eager', 
     advertiserKeywords: 'eager', 
     advertiserConnections: 'eager' 
] 

Этот код присутствует в ветви В, но отсутствует ветвь А. Когда я вытащить его, то теперь работает как и ожидалось.

Я решил сделать еще несколько копаний с этим кодом, чтобы увидеть, что я мог наблюдать. Я нашел что-то интересное, когда я использовал withCriteria вместо динамического искателя:

Advertiser.withCriteria{owner{idEq(ownerInstance.id)}}

То, что я обнаружил, что это вернулись тысячи дублей! Так что я попытался с помощью listDistinct:

Adviertiser.createCriteria().listDistinct{owner{idEq(ownerInstance.id)}}

Теперь это возвращает все 8 из моих рекламодателей, без дублей. Но что, если я попытаюсь ограничить результаты?

Advertiser.createCriteria().listDistinct{ 
    owner{idEq(ownerInstance.id)} 
    maxResults 25 
} 

Теперь это возвращает единственный результат, как и мой динамический искатель. Когда я свернул maxResults до 100K, теперь я получаю все 8 из моих результатов.

Так что же происходит? Кажется, что объединение или нетерпеливое извлечение (или оба) сгенерированного sql, которое вернуло тысячи дубликатов. Динамические поисковики Grails должны возвращать отличные результаты по умолчанию, поэтому, когда я не ограничивал их, я не заметил ничего странного. Но как только я установил предел, так как записи были упорядочены по идентификатору, первые 25 записей будут дублировать записи, а это означает, что будет возвращена только одна отдельная запись.

Что касается объединений и желающих, я не знаю, какую проблему пытался решить этот код, поэтому я не могу сказать, нужно ли это или нет; вопрос в том, почему этот код в моем классе генерирует так много дубликатов?

+0

Можете ли вы поделиться определением рекламодателя? Вы уверены, что это тот же владелецInstance в обоих? –

+2

Ваше приложение не должно влиять на это поведение. Более вероятными причинами могут быть такие вещи, как то, что вы указываете на две разные базы данных в разных ветвях или, возможно, на одну ветку есть проверки, которые другая не имеет, и вы создаете 8 рекламодателей в устройстве или бутстрапе, а создание не выполняется. – proflux

+0

Помните, что первая строка кода дает мне * все * моих рекламодателей * независимо от того, в какой ветке я нахожусь. Только когда я добавляю условия, я наблюдаю это поведение в ветке B. Поэтому я думаю, что исключает упомянутые возможности в комментариях выше. – Samo

ответ

1

Я узнал, что желающий выбор был добавлен (много уровней в глубину), чтобы ускорить рендеринг определенных отчетов, потому что делались сотни запросов. Попытки были предприняты для желаемого получения по требованию, но другим разработчикам трудно было пройти более одного уровня с помощью искателей или критериев Grails.

Таким образом, общий ответ на вопрос выше: вместо желания по умолчанию, что может привести к огромным ночным кошмарам в других местах, нам нужно найти способ сделать желаемый выбор из одного запроса, который может пройти более одного уровень вниз по дереву

Следующий вопрос: как? Это не очень хорошо поддерживается в Grails, но это может быть достигнуто просто с использованием класса критериев Hibernate. Вот суть его:

 def advertiser = Advertiser.createCriteria() 
      .add(Restrictions.eq('id', advertiserId)) 
      .createCriteria('advertiserConnections', CriteriaSpecification.INNER_JOIN) 
       .setFetchMode('serpEntries', FetchMode.JOIN) 
       .uniqueResult() 

Теперь рекламодатель advertiserConnections, будет стремиться неправдоподобным, и advertiserConnections 'serpEntries также будет стремиться неправдоподобным. Вы можете идти так далеко по дереву, сколько вам нужно. Тогда вы можете оставить свои классы ленивыми по умолчанию - что они определенно должны быть для hasMany сценариев.

0

Поскольку ваш запрос извлекает дубликаты, существует вероятность того, что этот предел в 25 записей будет возвращать одни и те же данные, следовательно, ваш отчет уменьшит до одной записи.

Постарайтесь определить equals() и hashCode() вашим классам, особенно если у вас есть составной первичный ключ или используется как hasMany.

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