Я пытаюсь найти наиболее эффективный способ выполнения определенного типа запроса с помощью Grails GORM.

Это сценарий, в котором я хочу запросить все дочерние / связанные элементы во взаимосвязи «многие к одному». Это односторонняя связь, при которой многие стороны использовали идентификатор объекта, с которым она связана.

Одним из примеров является взаимосвязь между учебным годом и семестрами этого учебного года. В таблице семестра идентификатор учебного года, к которому принадлежит семестр, хранится в таблице. Однако в таблице учебного года нет ничего, что можно было бы привязать к семестрам, которые ему принадлежат. Это сделано для того, чтобы количество семестров было гибким. Я надеялся использовать что-то вроде HQL для извлечения всех семестров, в которых они принадлежат одному и тому же учебному году. В обычном SQL мы можем фильтровать строки, используя столбец идентификатора учебного года в таблице семестра. В HQL все не так просто. Идентификатор учебного года недоступен как свойство класса домена. Вместо этого Hibernate просто использует его для загрузки фактического объекта учебного года.

Должно ли работать в этом случае что-то вроде ниже?

select from Semester as s where s.year.id = ?

В этом случае свойство семестрового доменного класса, в котором содержится учебный год, называется годом. Запрос берет свойство года и идентификатор этого года и использует его для фильтрации семестров.

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

Может быть более эффективный / действенный способ сделать это. Один из примеров - сделать фактическое значение идентификатора учебного года доступным из класса домена. Однако это будет означать, что один и тот же столбец сопоставлен более чем с одним свойством класса домена. Возможно, в этом нет необходимости, но это еще один возможный способ решения такой проблемы.

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

1
Carl Jokl 22 Окт 2010 в 13:30

2 ответа

Лучший ответ

Это похоже на базовое отношение 1: M, которое обрабатывается сопоставлениями ownTo / hasMany. Это не заставляет родительскую таблицу хранить какие-либо дополнительные данные. Просто имейте объекты домена:

class AcademicYear {
    static hasMany = [semesters: Semester]
}

class Semester {
    static belongsTo = AcademicYear
}

И у Семестра волшебным образом есть свойство «академический год», на которое вы можете ссылаться. И все, вобще как:

AcademicYear y = AcademicYear.findByYear(2010)
Semester s = Semester.get(1)
y.addToSemesters(s)
y.semesters.each{ println it }
String year = s.academicYear.name
def a = s.academicYear.id

Сначала попробуйте в "консоли grails" и наслаждайтесь.

1
Victor Sergienko 22 Окт 2010 в 18:21

Хотя gorm является еще одним слоем по сравнению со спящим режимом, он предоставляет эффективные критерии поиска и динамические средства поиска для обычных сценариев, а когда дело доходит до необычных сценариев, мы должны смотреть на запросы критериев. А когда дело доходит до еще более необычных сценариев, мы должны смотреть на hql, а для еще более сложных случаев мы можем также написать базовый sql.

Ниже приведены различные способы верхнего уровня, которые можно использовать для выполнения того или иного типа задач уровня запроса.

Предположим: у нас есть домен сотрудников, как показано ниже:

class Employee{
String name
int age
Designation designation

static hasMany = [teams:Team]
}
  1. ГОРМ динамические искатели:

     Employee.findByName("Ajay")
    
  2. Критерий запроса:

    Employee.createCriteria().list {
            eq 'name', 'Ajay'   
    }
    
  3. где пункт:

    Employee.where {
        name == 'ajay' && (age > 25 && age < 30)
    }.list()
    
  4. HQL :

    Employee.findAll('from Employee as e where e.name = :name', [name: 'Ajay'])
    
  5. Базовый sql:

    String query = $/
    SELECT * from employee e
    WHERE e.name = :name
    /$  
    new Employee()
    .domainClass
    .grailsApplication
    .mainContext
    .sessionFactory
    .currentSession
    .createSQLQuery(query)
        .setString('name', 'Ajay')
        .list()
    

Ниже представлена ​​более детальная иерархия для тех же, где да - подходит или применимо:

                    dynamic finder          where clause    criteria    HQL     SQL

    simple queries         yes                Yes             Yes        Yes    Yes

    complex filters                           Yes             Yes        Yes    Yes

    associations                              Yes             Yes        Yes    Yes

    property comparisons                      Yes             Yes        Yes    Yes

    some subqueries                           Yes             Yes        Yes    Yes

    eager fetches w/ complex filters                          Yes        Yes    Yes 

    projections                                               Yes        Yes    Yes 
    queries with arbitrary return sets                                   Yes    Yes

    highly complex queries (like self joins)                                    Yes

    some database specific features                                             Yes

    performance-optimized queries                                               Yes

Больше можно прочитать на http://tatiyants.com / how-and-when-to-use-different-gorm-querying-options /

0
Vinay Prajapati 18 Авг 2015 в 20:40