Reputation: 91
i have this issue when i want to save my object
My Customer
String firstName
String lastName
LocalDate dateOfBirth
CountryCode nationality
My CountryCode
@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
}
}
when i try to save my object i recieve this error
Class org.hibernate.TransientObjectException Message object references an unsaved transient instance - save the transient instance before flushing: lookup.iso.CountryCode
Do you have ideas how to fix this?
Thankx
Upvotes: 4
Views: 6964
Reputation: 11663
The specific reason for your error is because you haven't saved CountryCode before assigning it to the Customer, so Hibernate (the underlying ORM for Grails) considers it transient. Basically you do not have any GORM relationships (e.g, has*, belongsTo) defined. By defining a GORM relationship, you gain the ability to have cascade save/delete depending on how the relationships are defined.
Before simply adding hasOne or belongsTo to Customer and CountryCode respectively, you may want to consider how you are using CountryCode. Is CountryCode used as:
To implement #1, you should define just a uni-directional relationship using belongsTo
in CountryCode WITHOUT a hasOne
in Customer like so:
class CountryCode {
static belongsTo = [customer: Customer]
...
}
This will create a foreign key on the Customer table referencing a particular CountryCode - basically a one-to-many.
To implement #2, you should define a bi-directional relationship using belongsTo
in CountryCode WITH a hasOne
in Customer like so:
class Customer {
static hasOne = [country: CountryCode]
..
}
class CountryCode {
static belongsTo = [customer: Customer]
..
}
This will create a foreign key on the CountryCode table back to a particular Customer - basically a one-to-one mapping.
Upvotes: 2
Reputation: 4622
Use Grails relation convention
static hasOne = [nationality:CountryCode]
at Customer class and
static belongsTo = [customer:Customer]
at CountryCode class
Check grails docs about that, especially paragraph stating about cascade saves. If this doesn't fit your case than you need to call save() on CountryCode instance before assigning it to a Customer instance.
You can also use static embedded if apply to your case.
Another thing if you consider CountryCode as a dictionary entity, then load desired ContryCode instance from repository before assigning it to the Customer instance.
Upvotes: 2