在Grails中,我希望根据SQL查询设置一个瞬态变量。我必须使用SQL,而不是HQL。
(这是一个简化的示例。使用Grails 3.0.11。)
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()
中设置。
答案 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