Grails GORM устанавливает временные переменные из SQL-запроса - PullRequest
0 голосов
/ 26 марта 2019

В Grails мне бы хотелось, чтобы временная переменная была установлена ​​на основе SQL-запроса.Мне нужно использовать SQL, а не HQL.

(Это упрощенный пример. Использование Grails 3.0.11.)

  • Выполнение SQL-запроса
  • Какчасть SQL-запроса вычисляет значение для столбца
  • . Установите это значение в классе Entity и добавьте в SQL-запрос
  • См. ofLegalAge / of_legal_age ниже

Допустим, у меня есть следующий класс домена

 class Person {
    String firstName
    String lastName
    Integer age

    static mapping = {table "person"} 
 }

Тогда у меня будет представление о классе домена человека следующим образом

class PersonView {
    Long id
    String firstName
    String lastName
    // ofLegalAge is dynamically set based on query
    Boolean ofLegalAge
    // Other things based on joins

    static transients = [ "ofLegalAge" ]

    static mapping = {table "person_view"} 
}

Что я хотел бы сделать, это

 String sql = """select id, 
                        first_name, 
                        last_name, 
                        -- This is the source for of_legal_age
                        case when age >= :ageForThisArea 
                             then true 
                             else false 
                             end as of_legal_age
                 from view_person
                 where age >= :ageForThisArea"""

  def session = sessionFactory.getCurrentSession()
  def query = session.createSQLQuery(sql)
  query.setParameter("ageForThisArea", age)
  query.addEntity(PersonView)
  // This should result in a List of PersonView with ofLegalAge set correctly
  List<PersonView> theList = query.list()

В основном в конце мне нужно установить ofLegalAge на основе запроса, однако в конце (после вызова query.list()) он не устанавливается в PersonView.

Ответы [ 2 ]

0 голосов
/ 27 марта 2019

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

Я изменил запрос на

String sql = """select id, 
                       first_name, 
                       last_name, 
                       -- This is the source for of_legal_age
                       case when age >= :ageForThisArea 
                         then true 
                         else false 
                         end as of_legal_age
                from view_person
                where age >= :ageForThisArea"""

 def session = sessionFactory.getCurrentSession()
 def query = session.createSQLQuery(sql)
 query.setParameter("ageForThisArea", age)

 // Setting the Entity does not work
 // query.addEntity(PersonView)

 query.setResultTransformer(AliasToEntityLinkedMapResultTransformer.INSTANCE);
 List<Map> intermediateList = query.list()
 List<PersonView> theList = []

 for (Map oneRow : intermediateList) {
     PersonView pv = new PersonView(
       id : oneRow.id,
       firstName: oneRow.first_name,
       lastName: oneRow.last_name,
       ofLegalAge: oneRow.of_legal_age,
     )
     theList.add(pv)
 }

 return theList
0 голосов
/ 27 марта 2019

Переходный процесс означает, что он нигде не хранится в базе данных и рассчитывается на лету в доменной модели. Так почему бы просто не сделать что-то подобное в коде?

class PersonView {
    Long id
    String firstName
    String lastName

    // ofLegalAge is dynamically set based on query
    Boolean getOfLegalAge() { 
       //match the relevant record with Person here... your query doesn't do this?
       def matchedPerson = Person.findWhere(firstName: this.firstName, lastName: this.lastName)
       if (matchedPerson.age >= System.properties['ageForThisArea']) {
          return true
       } else { 
          return false
       }
     }

    static transients = ['ofLegalAge']

    static mapping = {table "person_view"} 
}


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

...