1

在我的 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,但如果有某种方法可以做到这一点,那将是一个奖励。

4

4 回答 4

1

I thought you could do:

class Parent    
  List children
  static hasMany = [children: Child]
}

And then the children are kept in a List, so implicitly have an index and order. I guess you actually want the elements to have an index field though rather than this implied ordering?

Edit

This works (it seems) but will hit the database every time you query the index

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

And makes me feel a little queasy ;-)

Edit 2

Of course, another alternative is:

  Integer getIndex() {
    parent.children.indexOf( this ) + 1
  }
于 2012-11-15T11:51:41.423 回答
0

您应该能够使用为 Grails 中的任何域类自动创建的 id 属性。默认情况下,对于保存到数据库的每个子项,此值都会递增。所以...

parent.children.sort {a,b -> a.id <=> b.id}

将按照保存到数据库的顺序返回父级的子级。

如果您绝对需要一个名为“index”的属性,我相信您可以执行以下操作:

Integer index

static mapping = {
    id name: 'index'
}

但是请注意,该索引可能是许多数据库中的保留字,因此您将无法拥有名为 index 的列,这将失败。考虑为您的财产取一个不同的名称。

于 2012-11-16T17:14:26.753 回答
0

使用具有自动增量的 id...一旦创建了一个孩子,它将永远不会使用另一个等于但更大的 id...如果您只需要知道创建顺序,您可以使用 id 或添加:

class Child{
    Date dateCreated;
    static belongsTo = [parent: Parent]
}

它将自动设置创建日期,您可以使用它来了解订单:)

于 2012-11-15T12:07:14.327 回答
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]
  }
}
于 2017-03-01T12:38:45.937 回答