从SQL查询Grails GORM设置瞬态变量

时间:2019-03-26 13:12:07

标签: grails gorm transient

在Grails中,我希望根据SQL查询设置一个瞬态变量。我必须使用SQL,而不是HQL。

(这是一个简化的示例。使用Grails 3.0.11。)

  • 执行SQL查询
  • 作为SQL查询的一部分,计算列的值
  • 已将在Entity类中设置的值添加到SQL查询中
  • 请参阅下面的ReadWriteLock / ofLegalAge

假设我具有以下Domain类

of_legal_age

然后我对Person Domain类有如下看法

 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()中设置。

2 个答案:

答案 0 :(得分:0)

瞬态表示它不存储在数据库的任何位置,而是在域模型中动态计算的。 那么,为什么不在代码中做这样的事情呢?

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"} 
}


这样,它将始终在飞行中查找。 如果要用数据预填充视图,则应该不要再使其成为瞬态数据,而是将其存储在某个位置。

答案 1 :(得分:0)

这是我发现可行的解决方案,但我绝对认为它不是最佳的,并且仍然会对更好的解决方案感兴趣。基本上,我将结果作为Map而不是使用Grails对象,然后手动将Map转换为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