【问题标题】:Grails object references an unsaved transient instanceGrails 对象引用了一个未保存的瞬态实例
【发布时间】:2013-04-16 10:28:06
【问题描述】:

当我想保存我的对象时遇到了这个问题

我的客户

String firstName
String lastName
LocalDate dateOfBirth
CountryCode nationality

我的国家代码

  @Audited
class CountryCode implements Serializable {

  String code
  String symbolA2
  String symbolA3
  String countryName

  static constraints = {
    code size:3..3, unique: true, matches: '[0-9]+'
    symbolA2 size:2..2, nullable: false, unique: true, matches: '[A-Z]+'
    symbolA3 size:3..3, nullable: false, unique: true, matches: '[A-Z]+'
    countryName size:1..50
  }

  static mapping = {
    id generator: 'assigned', name: 'code'
  }

  def beforeValidate() {
    symbolA2 = symbolA2?.toUpperCase()
    symbolA3 = symbolA3?.toUpperCase()
  }

  @Override
  String toString() {
    return countryName
  }
}

当我尝试保存我的对象时收到此错误

类 org.hibernate.TransientObjectException 信息 对象引用未保存的瞬态实例 - 在刷新之前保存瞬态实例:lookup.iso.CountryCode

您有解决此问题的想法吗?

谢谢

【问题讨论】:

  • 能否在实际执行保存时添加相关部分代码?

标签: grails grails-orm


【解决方案1】:

使用 Grails 关系约定

static hasOne = [nationality:CountryCode]

在客户类和

static belongsTo = [customer:Customer]

在 CountryCode 类

检查grails docs ,特别是关于级联保存的段落。 如果这不适合您的情况,则需要先调用 CountryCode 实例上的 save(),然后再将其分配给 Customer 实例。

如果适用于您的情况,您也可以使用static embedded

如果您将 CountryCode 视为字典实体,则另一件事,然后从存储库加载所需的 ContryCode 实例,然后再将其分配给 Customer 实例。

【讨论】:

    【解决方案2】:

    您的错误的具体原因是因为您在将 CountryCode 分配给客户之前没有保存它,所以 Hibernate(Grails 的底层 ORM)认为它是暂时的。基本上你没有定义任何 GORM 关系(例如,has*、belongsTo)。通过定义 GORM 关系,您可以获得级联保存/删除的能力,具体取决于关系的定义方式。

    在简单地将 hasOne 或 belongsTo 分别添加到 Customer 和 CountryCode 之前,您可能需要考虑如何使用 CountryCode。 CountryCode 是否用作:

    1. 一对多的查找/参考/字典实体,其中许多客户可以映射到特定的 CountryCode
    2. 一对一的唯一实体,每个客户都有一个唯一的 CountryCode

    要实现 #1,您应该在 CountryCode 中使用 belongsTo 定义一个单向关系WITHOUT 在 Customer 中使用 hasOne,如下所示:

    class CountryCode {
      static belongsTo = [customer: Customer]
      ...
    }
    

    这将在 Customer 表上创建一个引用特定 CountryCode 的外键 - 基本上是一对多。

    要实现 #2,您应该在 CountryCode 中使用 belongsTo 定义双向关系 WITH 在 Customer 中使用 hasOne,如下所示:

    class Customer {
      static hasOne = [country: CountryCode]
      ..
    }
    class CountryCode {
      static belongsTo = [customer: Customer]
      ..
    }
    

    这将在 CountryCode 表上创建一个外键,返回给特定的客户 - 基本上是一对一的映射。

    【讨论】:

    • 这是一个很好的解释和解决方案,当不是必需的关系时问题就来了,在我的情况下,'CountryCode'可以是也可以不是。
    猜你喜欢
    • 1970-01-01
    • 2010-12-20
    • 2011-04-12
    • 1970-01-01
    • 2014-01-23
    • 2014-06-29
    • 2013-01-04
    相关资源
    最近更新 更多