views:

51

answers:

1

I have a few domain classes, and I want to be able to populate a new Domain class and persist it to the database via one of my controllers. Here are my classes

class Employee implements Comparable
{
    static hasMany = [education:Education]
    static mapping = {
        education cascade:"all,delete-orphan", lazy:false
    }
    List<Education> education = new ArrayList<Education>();
}


public class Education implements Comparable
{
   static belongsTo = [employee:Employee]
   String collegeName
   String areaOfStudy
   String yearGranted
   Date lastModified
   Boolean inProcess = false;
   EducationType type = new EducationType(name:"None");
}


class EducationType
{
    String name="";
}

Now I want to create a new Education entry for a particular employee from this controller.

        def employee = Employee.get(session.empid);
        EducationType et = new EducationType(name:'JD')
        Education ed1 = new Education(collegeName:'Harvard1', areaOfStudy:'Law', yearGranted:'2015', type:et, lastModified:new Date(), employee:employee)

        employee.addToEducation(ed1)
        employee.save()

For some reason this is not behaving as expected and I get this exception:

2010-09-24 10:56:01,503 [http-8080-1] ERROR errors.GrailsExceptionResolver  - not-null property references a null or transient value: Education.type; nested exc
eption is org.hibernate.PropertyValueException: not-null property references a null or transient value: Education.type
org.springframework.dao.DataIntegrityViolationException: not-null property references a null or transient value: Education.type; nested exception is org.hiberna
te.PropertyValueException: not-null property references a null or transient value: Education.type
        at org.jsecurity.web.servlet.JSecurityFilter.doFilterInternal(JSecurityFilter.java:382)
        at org.jsecurity.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:180)
        at java.lang.Thread.run(Thread.java:619)
Caused by: org.hibernate.PropertyValueException: not-null property references a null or transient value: Education.type
        ... 3 more

I can get this to go away by first saving the EducationType with an et.save() and then saving the Education object with ed.save() and finally saving the employee.

Why is this necessary? Doesnt my mapping say that a save on employee should trickle down to any non-persisted objects that are now associated with the employee?

Also - why do I have to explicitly add employee when I initalize the Education object? It is specified in the belongsTo object, and it seems like when I do the employee.addToEducation() call it should be picked up automatically, right?

Thanks!

A: 

Your Education to EducationType is defined as a simple one-to-one. To cascade from Education to EducationType, I think you can make the latter belongTo the former. Check out 5.2.1.1 of the user guide. Note you have to be careful of what persistence semantics you want? Do you really want EducationTypes to be their own entities?

I think you have to add the employee to Education because you have a bidirectional one to many. Both sides of the relationship have to be set up. addToEducation works to add to the owning side of the relationship a member of the collection. Evidently, It does not set the relationship from the owned side to the owning side.

---- edit ----

I just looked at the docs because your second error seems wierd

"The addTo* method is a dynamic method that uses an association to automatically add instances to the association. It also automatically configures bi-directional relationship so that both sides o the relationship have been set."

So it seems that addTo should be setting both sides of the relationship...If you take the employee: employee out of your Education creation it does not work?

hvgotcodes
Thanks about the cascading note - that seems to have fixed my problems. Why is this the case though anyway? I thought by default on create cascading was the behavior. Are the defaults no longer available once you define one mapping? As for my second problem, I can't seem to reproduce it after fixing the cascading problem - maybe it was an issue with the object not being valid before or something. If I can make it happen again I will post here.
Derek
@Derek, I dont think cascading is ever the default with non-grails enabled hibernate; in grails they might do some things to help, but you need to have the docs ready to confirm.
hvgotcodes