【问题标题】:What is the correct Grails ORM (GORM) implementation to use?要使用的正确 Grails ORM (GORM) 实现是什么?
【发布时间】:2015-03-03 11:29:19
【问题描述】:

作为更改请求的结果,我需要为我的 Grails 应用程序实现正确的 ORM。

我目前有以下简单的模型和关联:

  • 代理

    static hasMany = [fees:Fee]
    
  • 费用

    static belongsTo = [agent:Agent]
    

但是,现在我需要实现在代理之间分配单一费用的功能。我最终得到以下结果:

潜在的新模型协会

  • 费用

    static hasMany = [agentfees:AgentFee]
    
  • 代理

    no associations ??
    
  • 代理费

    static belongsTo = [fee:Fee]
    

在我看来,AgentFee 将包含:

  • 对费用的引用
  • 对代理的引用
  • 代理的费用分成百分比(例如 80%)

所以我的问题是。我是否还应该在 Agent 和 AgentFees 之间建立关联,例如:

  • 费用

    static hasMany = [agentfees:AgentFee]
    
  • 代理

    static hasMany = [agentfees:AgentFee]
    
  • 代理费

    static belongsTo = [fee:Fee]
    static belongsTo = [agent:Agent]
    

但这只是感觉 AgentFee 中的多个 belongsTo 有问题。使用 GORM 实现“费用分割”概念的最佳方式是什么?

提前致谢,

约翰

【问题讨论】:

  • 你试过static belongsTo = [fee:Fee, agent:Agent]吗?
  • 谢谢你。我没有尝试过,但我的问题更多——我的建模方式一开始就正确吗?我的“费用分摊”方法正确吗?
  • 对我来说看起来不错,但是,根据我的经验 - 如果您不使用脚手架控制器(大多数时候您不使用)也不使用自动数据库模式创建(另外,您应该t),然后使用 belongsTo 和 hasMany 属性带来的痛苦多于收获 - 就我个人而言,我只将引用作为域类中的常规字段而不是 belongsTo,并且完全跳过 hasMany
  • @kamil 如果你不使用 hasMany 你如何映射你的一对多关系?你的建议似乎不合理。
  • 如果您不将 hasMany 用于一对多关系,我也会担心。

标签: grails orm model associations grails-orm


【解决方案1】:

听起来您正在将关系更改为多对多。这是相关的文档:http://grails.github.io/grails-doc/latest/guide/GORM.html#manyToMany

多对多关系需要数据库级别的连接表。但是,您很可能不需要加入表的域,即您不需要 AgentFee。 GORM 会知道使用连接表。

您的联接表需要域对象的唯一情况是,如果联接表具有促进多对多关系所需的列之外的其他列。在这种情况下,您将为连接表创建一个域,然后创建两个一对多关系,每个方向一个。

【讨论】:

  • 谢谢。回覆。 - 在多对多中不需要连接表的域,除非连接表具有超出促进多对多关系所需的列之外的其他列 - 在这种情况下,我需要知道代理有权收取的费用。所以这会让我相信我需要你的第二个例子,它是“连接表的域,然后创建两个一对多的关系,每个方向一个。”即我在原始问题中概述的内容在您看来是正确的?
  • @JohnR 是的,它看起来是正确的。我查看了一些代码,它有一个连接表,其中包含多对多的附加列,而我的看起来就像你的一样(即连接域中有两个 belongsTo)
  • 非常感谢,只是感觉有点“奇怪”,但很高兴得到一些澄清
【解决方案2】:

回答cmets的问题:

@Michael @John 如果您查看底层数据库表,那么您只会看到从一个表到另一个表的外键,除非它是一对一的,否则表不会交叉引用,因此像我一样简化域类前面描述的物理数据没有任何变化,并且更容易在代码中维护(您不必使用 addTo()removeFrom 方法),您只需创建一个依赖对象并将其设置为当前的引用(您总是只更改一件事)

Agent a = new Agent()
Fee fee = new Fee(

另外,如果您想检索所有相关对象,您可以创建一个属性返回列表,如

class Fee {
    Agent agent
}
class Agent {
    List<Fee> getFees() { 
        Fee.findAllByAgent(this) 
    }
}

并像使用它一样

Agent a = new Agent()
List<Fee> aAgentsFees = a.fees

当然它是只读的,如果你想创建它们:

Agent agent1 = new Agent()
Fee feeA = new Fee(agent: agent1)
Fee feeB = new Fee()
feeB.agent = agent1

【讨论】:

  • 我没有看到使用 hasMany 的任何优势,我看到的只是劣势。首先,使用 hasMany 是处理多方面关系的标准 GORM 方式,因此您的代码的未来维护者将不得不弄清楚您的代码是如何工作的以及为什么要这样做。此外,您的方式不允许您利用批量设置操作(removeAll 和 retainAll)来管理关系多方面的添加/更新/删除。
  • 感谢您的努力,也非常感谢 - 但只是补充一下,请注意文档中的这一点:“默认的级联行为是级联保存和更新,但不会删除,除非是 belongsTo也被指定”
  • @Michael 我不是说我是对的,你的错,我只是说我 4 年的 grails 经验带来了什么:) 早在 2.0.0 版本左右就有问题涉及 hasMany 关系的单元测试,以及 - 与同事一起 - 我们注意到,如果你想连接两个对象,你必须同时在 belongsTo 一侧设置关系以及在另一侧使用 addTo,这可能会忘记一个其中 - 在 5 或 6 个 grails 项目之后,我停止使用 hasMany/belongsTo 并且我还将动态查找器视为私有的,这对我来说效果更好 4
  • @JohnR - 是的,也许可以,但是如果您使用 db 迁移并至少自己管理部分数据库架构,那么您可以轻松地在删除时设置数据库级联,并且它的工作方式相同
猜你喜欢
  • 1970-01-01
  • 2019-07-16
  • 2020-07-21
  • 2010-10-05
  • 2011-11-06
  • 2018-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多