在我的Grails应用程序中,我有两个具有一对多关系的域类,例如
class Parent
static hasMany = [children: Child]
}
class Child {
Integer index
static belongsTo = [parent: Parent]
}
我希望index
记录创建子项的相对顺序,这样父项的第一个子项将具有索引1,下一个将具有2,等等。索引没有是连续的,因为孩子可以被删除,但他们应该总是反映创造的相对顺序。
我考虑过做类似以下的事情来设置index
属性
class Child {
Integer index
static belongsTo = [parent: Parent]
def beforeValidate() {
def maxIndex = Child.createCriteria().get {
projections {
max('index')
}
eq('parent', parent)
}
this.index = maxIndex + 1 ?: 1
}
}
但当然这不起作用,因为它会为两个瞬态Child
实例分配相同的索引。维护此index
属性的最简单方法是什么?
FWIW,我并不太关心阻止任何其他代码设置index
但是如果有某种方法可以做到这一点,那就是奖金。
答案 0 :(得分:1)
我以为你可以做到:
class Parent
List children
static hasMany = [children: Child]
}
然后将子项保存在List中,因此隐式具有索引和顺序。我猜你真的希望元素有一个索引字段而不是这个隐含的顺序吗?
这可行(似乎)但每次查询索引时都会命中数据库
class Child {
def grailsApplication
static belongsTo = [ parent: Parent ]
Integer getIndex() {
grailsApplication.mainContext.sessionFactory.currentSession.with { sess ->
createSQLQuery( 'SELECT c.children_idx FROM child c where c.id = :id' )
.setBigInteger( "id", this.id )
.list()
.head() + 1
}
}
String toString() {
"Child @$index"
}
}
让我感到有些不安; - )
当然,另一种选择是:
Integer getIndex() {
parent.children.indexOf( this ) + 1
}
答案 1 :(得分:0)
使用带有自动增量的id ...一旦创建了一个子项,它将永远不会使用另一个id等于但更大......如果你只需要知道创建的顺序,你可以使用id或添加一个:
class Child{
Date dateCreated;
static belongsTo = [parent: Parent]
}
它会自动设置创建日期,您可以使用它来了解订单:)
答案 2 :(得分:0)
您应该能够使用为Grails中的任何域类自动创建的id属性。默认情况下,对于保存到DB的每个子项,此值将递增。所以......
parent.children.sort {a,b -> a.id <=> b.id}
将按照保存到数据库的顺序返回父项的子项。
如果您绝对需要名为“index”的属性,我相信您可以执行以下操作:
Integer index
static mapping = {
id name: 'index'
}
但是,请注意,索引可能是许多数据库中的保留字,因此您将无法拥有名为index的列,这将失败。考虑一下您房产的不同名称。
答案 3 :(得分:0)
您可以使用indexColumn grails映射功能
https://docs.grails.org/latest/ref/Database%20Mapping/indexColumn.html
Class Parent(){
static hasMany = [children: Child]
List children // Generates column `book_idx` in table for Book.
static mapping = {
children indexColumn: [name: "index", type: Integer]
}
}