【问题标题】:Multiple many-to-many associations in one Grails domain class一个 Grails 域类中的多个多对多关联
【发布时间】:2015-12-28 16:04:47
【问题描述】:

我正在使用 Grails 3.0.6,并且正在努力处理一个复杂且高度互连的域模型。我的类与其他类有多个多对多关联,我别无选择,只能在至少一个类上有多个 belongsTo 关联。我无法弄清楚表示这一点的语法。

我的领域模型非常复杂,但我能够将我的问题简化为这个简化的示例:

class Graph {
    static hasMany = [vertices: Vertex]
}

class OtherClass {
    static hasMany = [vertices: Vertex]
}

class Vertex {
    static hasMany = [graph: Graph, other: OtherClass]
}

在这个简化的示例中,我可以通过声明 Graph 和 OtherClass 上的域类之间的所有权来解决这个问题......在我复杂的域模型中,我没有这个选择,因为有太多的类有多个多对多关联。

我试过这个:

class Vertex {
    static hasMany = [graphs: Graph, others: OtherClass]
    static belongsTo = Graph, OtherClass
}

但我得到了一个 NPE。

我试过这个:

class Vertex {
    static hasMany = [graphs: Graph, others: OtherClass]
    static belongsTo = [graphs: Graph, others: OtherClass]
}

但我仍然收到“GrailsDomainException:域类 [Graph] 和 [Vertex] 之间未定义所有者”

我可以用 mappedBy 做些什么来正确表示这个吗?

在我的许多多对多关联中,实际上并不需要级联保存(尽管它们不会造成伤害),因此我不需要为此目的使用 belongsTo(或“所有者”)。这让我想知道域类上的关联是否真的是我应该如何建模这些关系。还有什么我可以做的吗?

【问题讨论】:

  • 考虑将连接表与域类显式映射,例如 spring-security-core UserRole 类。
  • @BurtBeckwith 你在说这个,对吧? github.com/grails-plugins/grails-spring-security-core/blob/…我以前见过类似的事情。如果我创建一个名为 VertexGraph 的类,它会映射到连接表吗? VertexGraph 与 GraphVertex 重要吗?
  • 是的 - 它不太方便,但您可以获得更多控制权(并且不会因集合而出现性能问题)。使用此方法时,某些条件查询不起作用,但我可以帮助解决任何具体问题
  • @BurtBeckwith 我能够让我的玩具示例与您的建议一起使用 - 请参阅下面的答案。这就是你的想法吗?

标签: grails grails-orm grails-3.0


【解决方案1】:

根据 Burt Beckwith 的评论,我创建了一个额外的域类来表示连接表。现在,一个多对多关联被分解成两个一对多关联,问题就不会出现了。

例子:

class Graph {
    static hasMany = [graphVertexRelations: GraphVertexRelation]
}

class OtherClass {
    static hasMany = [vertices: Vertex]
}

class Vertex {
    static hasMany = [graphVertexRelations: GraphVertexRelation, others: OtherClass]
    static belongsTo = OtherClass
}

class GraphVertexRelation {
    static belongsTo = [graph: Graph, vertex: Vertex]

    static GraphVertexRelation create(Graph graph, Vertex vertex, boolean flush = false) {
        new GraphVertexRelation(graph: graph, vertex: vertex).save(flush: flush, insert: true)
    }
}

【讨论】:

  • 我将删除 hasMany 和 belongsTo 属性并管理连接类中的所有内容,以避免集合的不必要的性能开销。请参阅this talk 了解更多信息
【解决方案2】:

您看到的异常"GrailsDomainException: No owner defined between domain classes [Graph] and [Vertex]" 表示 ORM 无法确定基类是什么,并且 Graph 和 Vertex 之间存在循环关系。

如果您想保持关系以查看顶点所在的 Graph,您可以使用条件进行向后查找。

class Graph {
    static hasMany = [vertices: Vertex]
}

class OtherClass {
    static hasMany = [vertices: Vertex]
}

class Vertex {
    static transients = ['graphs']
    static hasMany = [other: OtherClass]

    List<Graph> getGraphs() {
        // Backwards link, using the graph table
        Graph.withCriteria() {
            vertices {
                inList("id", [this.id.toLong()])
            }
        }
    }
}

【讨论】:

  • 我真的需要多对多的关系。如果我正确理解瞬变,这将在 Graph 和 Vertex 之间创建一对多的关系。我需要 Vertex 能够位于多个 Graphs 中。
  • 好的。这是您的数据模型,您显然有未列出的约束。鉴于您在“顶点”类中根本没有属性,我假设您可能不需要在图中具有相同的确切顶点实例,而您可以只在 OtherClass(s) 中使用共享信息。附言出于性能原因,使用大多数图形算法,您很可能不应该将图形对象存储在关系数据库中。
猜你喜欢
  • 2014-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-08
相关资源
最近更新 更多