【问题标题】:Grails GORM Set Transient Variables from SQL QueryGrails GORM 从 SQL 查询设置瞬态变量
【发布时间】:2019-08-16 21:20:42
【问题描述】:

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

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

  • 执行 SQL 查询
  • 作为 SQL 查询的一部分,计算列的值
  • 将该值设置在实体类中添加到 SQL 查询中
  • 见下方ofLegalAge / of_legal_age

假设我有以下域类

 class Person {
    String firstName
    String lastName
    Integer age

    static mapping = {table "person"} 
 }

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

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

【问题讨论】:

  • @Vahid 谢谢,但是 (a) PersonView 类已存在并用于许多其他事情,并且 (b) 正如我所提到的,我需要 SQL 用于与此问题分开的查询的其他部分
  • 想知道如果您将其更改为字符串是否可行?你可以尝试 CAST(1 AS BIT) ELSE CAST(0 AS BIT) END 按照stackoverflow.com/questions/10377781/…

标签: grails grails-orm transient


【解决方案1】:

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

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


这样它总是会被即时查找。 如果您想使用数据预先填充视图,您应该不再将其设为瞬态并将其存储在某个地方。

【讨论】:

  • 我明白什么是瞬态。请注意,我的问题是实际问题的(非常)简化版本,以便获得解决方案。我不能按照你的建议去做,因为真正的问题不在于年龄。实际的问题是如何将查询结果数据绑定到 Grails 对象中
  • 抱歉并不是粗鲁的意思。我认为我没有完全理解这个问题。仍然不确定我是否这样做。你能不能不使用上面的东西,但在 getter 中使用 sql 来做你的查找?如stackoverflow.com/a/19165211/708998 所示,如果您的数据源与mrhaki.blogspot.com/2014/03/… 所示完全不同,甚至直接使用sql。如果您想保存和使用该字段,则可以将其设为字段并在 beforeinsert 或 onLoad 事件中设置它gorm.grails.org/latest/hibernate/manual/…
  • 我也很抱歉。我查看了您的建议,但找不到任何有效的方法
【解决方案2】:

我发现这是一个可行的解决方案,但我绝对认为它不是最理想的,并且仍然对更好的解决方案感兴趣。基本上我将结果作为 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多