Sac*_*hin 3 grails grails-orm grails-domain-class
我正在尝试在 grails 中为以下域编写一个条件查询:
class Data {
Long createdById // this is user id
// other fields
}
class User {
Company company
// other fields
}
Run Code Online (Sandbox Code Playgroud)
现在数据,顾名思义存储一些数据。它与User没有直接关系,但有一个字段createdById,它是User的id。
(我无法在数据中直接引用用户,因为这些属于不同的项目,其中数据来自自定义可重用插件。)
现在我想在数据上编写标准并列出由给定公司的用户创建的所有记录。那是data.id == User.id and user.company == givenCompany
为了使用任何 GORM/Hibernate 查询方法(criteria、where 或 HQL),您需要域类之间的关联。由于您无法从Datato建立关联User,因此您无法使用 GORM 来编写您的查询与您的域类(它们是)。换句话说,你需要使用SQL;HQL(DomainClass.executeQuery()不起作用)。但...
如果你愿意修改User和维护一些冗余数据,你可以使用HQL。
class User {
Company company
// other fields
/* Add uni-directional one-to-many */
static hasMany = [data: Data]
}
def data = AnyDomainClass.executeQuery('SELECT d FROM User as u INNER JOIN u.data AS d WHERE u.company = :company', [company: givenCompany])
Run Code Online (Sandbox Code Playgroud)
单向一对多关联创建一个需要维护的连接表以反映Data.createdById. HQL 连接语法暗示了需要关联这一事实。如果您必须使用条件查询...
要使用条件查询,您需要修改User并添加额外的域类。原因是条件查询无法像 HQL 那样投影关联。例如,这将不起作用:
def data = User.withCriteria {
eq('company', givenCompany)
projections {
property('data')
}
}
Run Code Online (Sandbox Code Playgroud)
由于无法修改Data,这——这是最简单的解决方案——也将不起作用:
def data = Data.withCriteria {
user {
eq('company', givenCompany)
}
}
Run Code Online (Sandbox Code Playgroud)
因此,您需要一个中间人来投影Data实例:
class User {
Company company
// other fields
static hasMany = [userData: UserData]
}
class UserData {
Data data
static belongsTo = [user: User]
}
def data = User.withCriteria {
eq('company', givenCompany)
projections {
userData {
property('data')
}
}
}
Run Code Online (Sandbox Code Playgroud)
可以想象,这种方法也需要一些数据维护。
最后,您可以选择使用 SQL 并让查询返回域类实例。归结起来是这样的:
AnyDomainClass.withNewSession { session ->
def data = session.createSQLQuery('SQL GOES HERE').addEntity(Data).list()
}
Run Code Online (Sandbox Code Playgroud)
欲了解更多信息,请查看我的以下文章: