2013-06-18 3 views
5

Ho una tabella che memorizza una gerarchia di agenti:Grails/GORM mappatura non standard-Nominato chiave esterna

create table agent (
    agent_id int not null, 
    agent_name varchar(255), 
    agent_parent_id, 
    constraint pk_agent primary key (agent_id)); 

alter table agent 
    add constraint fk_agent_agent foreign key (agent_parent_id) references (agent_id); 

ho modellato come:

class Agent { 
    String agentName 
    Agent agentParent 
    static mapping = { 
    id column: 'agent_id' 
    id generator: 'sequence', params: [sequence: 'agent_id_seq'] 
    } 
} 

Ogni agente può hanno molte proprietà:

create table agent_property (
    agent_property_id int not null, 
    agent_property_name varchar(255), 
    agent_id int, 
    constraint pk_agent_property primary key (agent_property_id)); 

alter table agent_property (
    add constraint fk_agent_property_agent foreign key (agent_id) references agent(agent_id); 

ho modellato che come:

class AgentProperty { 
    String agentPropertyName 
    static hasOne = [agent: Agent] 
    static mapping = { 
    id column: 'agent_property_id' 
    id generator: 'sequence', params: [sequence: 'agent_property_id_seq'] 
    } 
} 

ho creato un vista per vedere facilmente la gerarchia degli agenti:

create view pathogen as 
    select c.agent_id as id, a.agent_name as genus, b.agent_name as species, c.agent_name as strain, d.agent_name as toxin 
    from agent a 
    left join agent b on a.agent_id = b.agent_parent_id 
    left join agent c on b.agent_id = c.agent_parent_id 
    left join agent d on c.agent_id = d.agent_parent_id 
    where a.agent_parent_id is null; 

il mio problema è nel modellare la vista patogeno. Ho fatto questo:

class Pathogen { 
    String genus 
    String species 
    String strain 
    String toxin 
    static hasMany = [agentProperties: AgentProperty] 
} 

Ciò implica che non v'è una chiave esterna 'pathogen_id' nella tabella agent_property. Ma non è questo il caso. La chiave esterna è agent_id. Voglio AgentProperty di relazionarsi con agenti patogeni sulla agent_id come se ci fosse il vincolo:

alter table agent_propery 
    add constraint fk_agent_property_pathogen foreign key (agent_id) references pathogen (id); 

ho cercato di mappare i agentProperties proprietà implicite al agent_id nella mia classe Pathgeon, qualcosa di simile:

static mapping = { 
    agentProperties column: agent_id // or AgentProperty.agent 
} 

ma quello non ha funzionato.

Come comunicare a GORM di utilizzare agent_property.agent_id come chiave esterna?

risposta

6

La soluzione al mio problema originale è che non sono riuscito a inserire agent_id tra virgolette.

agentProperties column: 'agent_id' 

Questo funziona ora:

class Pathogen { 
    String genus 
    String species 
    String strain 
    String toxin 

    static hasMany = [agentProperties: AgentProperty] 

    static mapping = { 
    // use agent_id to releate to AgentProperty 
    agentProperties column: 'agent_id' 
    } 
} 

class AgentProperty { 
    String agentPropertyName 

    static belongsTo = [agent: Agent] 
    static hasOne = [pathogen: Pathogen] 

    static mapping = { 
    id column: 'agent_property_id' 
    id generator: 'sequence', params: [sequence: 'agent_property_id_seq'] 
    // use agent_id to relate to Pathogen 
    pathogen column: 'agent_id', insertable: false, updateable: false 
    } 
} 
0

vostre classi di dominio ha bisogno di po 'di modifica a bastone per il disegno che avete in banca dati,

class Agent { 
    String agentName 
    Agent agentParent 

    //agent_id Foreign Key to AgentProperty. Agent has many AgentProperties 
    static hasMany = [agentProperties: AgentProperty] 

    static mapping = { 
    id column: 'agent_id' 
    id generator: 'sequence', params: [sequence: 'agent_id_seq'] 
    } 
} 

class AgentProperty { 
    String agentPropertyName 

    //AgentProperty belongs to an Agent. Cascade delete is enabled 
    static belongsTo = [agent: Agent] 
    static mapping = { 
    id column: 'agent_property_id' 
    id generator: 'sequence', params: [sequence: 'agent_property_id_seq'] 
    } 
} 

class Pathogen { 
    String genus 
    String species 
    String strain 
    String toxin 

    //like foreign key pathogen_id in agent table 
    static hasMany = [agents: Agent] 
} 

È possibile entrare in possesso di AgentProperty da Pathogen via Agent.

Se ho letto correttamente la tua domanda, allora questo è quello che ti serve.

Pathogen hasMany Agents 
Agent hasMany AgentProperty 
+0

Grazie dmahapatro. Non c'è pathogen_id nella tabella degli agenti e non posso cambiarlo. Inoltre, il patogeno-agente non è uno-a-molti. Se mai, sarebbe 1: 1. Pathogen è una VISTA nel database. Si potrebbe dire che il patogeno ha un agente in cui pathogen.id == agent_id, ma ogni agente non ha un agente patogeno. –

+0

@MarkAnderson Spiacente di non aver capito che 'Pathogen' è un db' view'. Hai davvero bisogno di quella vista perché puoi usare la query sui criteri su "Agent" e "AgentProperty" per ottenere quello che vuoi. La query di selezione utilizzata nella vista può essere convertita in [Criteria] (http://grails.org/doc/2.2.1/ref/Domain%20Classes/createCriteria.html). Se è necessario utilizzare la vista [ ecco come puoi accedervi] (http://stackoverflow.com/questions/425294/sql-database-views-in-grails). – dmahapatro

+0

Per modellarlo, potrei fare 'class Pathogn {String genus; Specie per archi; Sforzo per le corde; Tossina delle stringhe; Agente agente}; static mapping = [column agent: 'agent_id']} –