6
votes

I am trying to use an embedded domain with a many-to-one relationship in Grails 2.2.1. Here's a simplified version of what I am trying to do.

I'm mapping to existing db tables:

create table incident (id bigint generated by default as identity, state_id bigint not null, primary key (id));
create table state (id bigint generated by default as identity, name varchar(255) not null, primary key (id));
alter table incident add constraint FK52F44D27499E79E foreign key (state_id) references state;

Domains that map to "incident" table:

class Incident {
    Vehicle vehicle
    static embedded = ['vehicle']
}

class Vehicle{
    State state
    static mapping = {
        state column: 'state_id'
    }   
}  

Domain that maps to "state" table:

class State {
    String name 
}

When I try to run my application, I get the following error:

Message: Error creating bean with name 'transactionManagerPostProcessor': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager': Cannot resolve reference to bean 'sessionFactory' while setting bean property 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory': Invocation of init method failed; nested exception is org.hibernate.MappingException: Could not determine type for: test.State, at table: incident, for columns: [org.hibernate.mapping.Column(vehicle_state)]

Is it possible to have a many-to-one association within an embedded domain?

--Update--

I ended up using a workaround to get the state.

class Vehicle{

    static transients = [ "state" ]

    Long stateId

    static mapping = {
        stateId column: 'state_id'  
    }

    State getState(){
        State.get(this.stateId)
    }
}
2
I'm starting to think this might be a grails bug... Sounds similar to jira.grails.org/browse/GRAILS-9012Becca Gaspard

2 Answers

4
votes

As of Grails 2.2.1, embedded domain classes have several usability issues that make them difficult to work with, especially in legacy databases.

  1. Relationships do not work
  2. Custom column mappings do not work

You're better off mapping the column directly in the owning class, then creating a helper method to deal with the embedded entities.

e.g.:

// grails-app/domain/yourpkg/Incident.groovy
class Incident {
    State state

    public Vehicle getVehicleData() {
        return new Vehicle(state: state)
    }

    public void updateWithVehicle(Vehicle vehicle) {
        state = vehicle.state
    }

    static mapping = {
        state column: 'state_id'
    }
}

// src/groovy/yourpkg/Vehicle.groovy
class Vehicle {
    State state
}
0
votes

In this case the domains have to be serialized (including the embedded Vehicle which will not be part of persistence if moved to src/groovy) and generate equals() hashCode() for the classes. Old school but works good, app run appropriately.

Incedent.groovy

import groovy.transform.EqualsAndHashCode

@EqualsAndHashCode
class Incedent implements Serializable{
    Vehicle vehicle
    static embedded = ['vehicle']

    class Vehicle{
        State state
    }
}

State.groovy

import groovy.transform.EqualsAndHashCode

@EqualsAndHashCode
class State implements Serializable {
    String name
}

Following the above you would get a column in Incedent for the embedding with a datatype of VARBINARY (when tested with in memory H2 db). I would prefer having the stateName as a String in Vehicle

enter image description here