0

I have 2 domain classes; the forst of them represents an email address, with the name of the user and the email address itself. The other class represents an email message, with the subject, the sender (one email address) and the recipients (a list of email addresses):

class EmailMessage {
    static hasMany = [ to: EmailAddress ]
    EmailAddress from
    String subject
}

class EmailAddress {
    String name
    String address
}

But this code doesn't work as I expect:

EmailMessage msg = new EmailMessage()
msg.from = new EmailAddress(name: "User 1", address: "user1@domain.com")
[new EmailAddress(name: "User 2", address: "user2@domain.com"), new EmailAddress(name: "User 3", address: "user3@domain.com")].each {
    msg.addToTo(it)
}
msg.subject = "Asunto"
msg.save(failOnError: true)

I get this error:

| Error 2013-08-14 21:08:40,362 [localhost-startStop-1] ERROR util.JDBCExceptionReporter  - La columna "FROM_ID" no permite valores nulos (NULL)
NULL not allowed for column "FROM_ID"; SQL statement: insert into email_message (id, version, from_id, subject) values (null, ?, ?, ?) [23502-164]
| Error 2013-08-14 21:08:40,375 [localhost-startStop-1] ERROR context.GrailsContextLoader  - Error initializing the application: could not insert: [prueba.EmailMessage];
SQL [insert into email_message (id, version, from_id, subject) values (null, ?, ?, ?)]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not insert: [prueba.EmailMessage]
Message: could not insert: [prueba.EmailMessage]; SQL [insert into email_message (id, version, from_id, subject) values (null, ?, ?, ?)]; constraint [null];
nested exception is org.hibernate.exception.ConstraintViolationException: could not insert: [prueba.EmailMessage]

I don't know if this even can be done, or the cascade save doesn't work as I suppose.

I thik I have tried all combinations of hasMany, belongsTo, etc. in each class, without success.

I have also read this topic but it doesn't work as expected Grails hasOne and hasMany same domain.

Could any one help me? Regards and thanks in advance.

Community
  • 1
  • 1
okelet
  • 716
  • 1
  • 8
  • 23

2 Answers2

1

Unfortunately you have to save your from before you save the parent.

EmailMessage msg = new EmailMessage()
msg.from = new EmailAddress(name: "User 1", address: "user1@domain.com")
if (!msg.from.save(flush: true)) {
    log.error("message could not be saved: " + msg.from.errors)
}
[new EmailAddress(name: "User 2", address: "user2@domain.com"), new EmailAddress(name: "User 3", address: "user3@domain.com")].each {
    msg.addToTo(it)
}
msg.subject = "Asunto"
msg.save(failOnError: true)

There is no cascading save in a 1:1 relation.

Chris
  • 8,031
  • 10
  • 41
  • 67
1

This works for me in the standard memory database

class EmailMessage {
    static hasMany = [ to: EmailAddress ]
    EmailAddress from
    String subject

    static mapping = {
        from cascade: "save-update" //Pretty sure this is unnecessary
    }
}

class EmailAddress {
    String name
    String address

    static belongsTo = EmailMessage
}
James Kleeh
  • 12,094
  • 5
  • 34
  • 61
  • You are right. The mapping block is not necessary, as long in my short tests. The rest of the code works great now. Thanks! – okelet Aug 16 '13 at 18:08
  • throws: ```org.springframework.dao.InvalidDataAccessApiUsageException: Not-null property references a transient value - transient instance must be saved before current operation : test.Child.parent -> test.Parent; nested exception is org.hibernate.TransientPropertyValueException: Not-null property references a transient value - transient instance must be saved before current operation : test.Child.parent -> test.Parent``` any idea how can i fix it? – Sachin Jul 29 '16 at 18:10