2013-06-18 9 views
5

ich eine Tabelle, die eine Hierarchie von Agenten speichert:Grails/GORM Mapping, um Non-Standard-Named Foreign Key

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); 

Ich habe es als Vorbild:

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

Jeder Agent kann viele Eigenschaften haben:

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); 

ich habe modelliert, dass als:

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

ich eine Ansicht erstellt haben einfach die Hierarchie von Agenten zu sehen:

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; 

Mein Problem ist, den Erreger Ansicht bei der Modellierung. Ich habe dies getan:

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

Dies bedeutet, dass es ein Fremdschlüssel ‚pathogen_id‘ in der agent_property Tabelle. Aber das ist nicht der Fall. Der Fremdschlüssel ist agent_id. Ich mag AgentProperty zu Pathogen auf agent_id beziehen, als ob es die Einschränkung war:

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

ich die implizite Eigenschaft agentProperties abzubilden versucht, in meiner Pathgeon Klasse agent_id, so etwas wie:

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

aber das hat nicht funktioniert.

Wie kann ich GORM anweisen, agent_property.agent_id als Fremdschlüssel zu verwenden?

Antwort

6

Die Lösung für mein ursprüngliches Problem ist, dass ich in Anführungszeichen zu setzen agent_id gescheitert.

agentProperties column: 'agent_id' 

Das funktioniert jetzt:

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

braucht Ihre Domain Klassen wenig Modifikation der Entwurf, den Sie in Datenbank zu halten,

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] 
} 

Sie halten AgentProperty von Pathogen über Agent bekommen.

Wenn ich Ihre Frage richtig gelesen habe, dann ist das, was Sie brauchen.

Pathogen hasMany Agents 
Agent hasMany AgentProperty 
+0

Dank dmahapatro. Es gibt keine pathogen_id in der agent-Tabelle, und ich kann das nicht ändern. Außerdem ist Pathogen-zu-Agens nicht eins zu viele. Wenn überhaupt, wäre es 1: 1. Pathogen ist eine Sicht in der Datenbank. Man könnte sagen, dass der Erreger einen Agenten hat, wo pathogen.id == agent_id, aber jeder Erreger hat keinen Erreger. –

+0

@MarkAnderson Tut mir leid, ich habe nicht bemerkt, dass "Pathogen" eine db 'view' ist. Brauchen Sie diese Ansicht wirklich mehr, weil Sie die Kriterienabfrage für 'Agent' und' AgentProperty' verwenden können, um zu bekommen, was Sie wollen. Die ausgewählte Abfrage, die in der Ansicht verwendet wird, kann in eine [Kriterien] (http://grails.org/doc/2.2.1/ref/Domain%20Classes/createCriteria.html) konvertiert werden. Wenn Sie dazu aufgefordert werden, die Ansicht zu verwenden [ Hier ist, wie Sie darauf zugreifen können] (http://stackoverflow.com/questions/425294/sql-database-views-in-grails). – dmahapatro

+0

Um das zu modellieren, könnte ich 'Klasse Pathogn {String genus; String-Arten; String Belastung; Schnur-Toxin; Agent Agent}; static mapping = [Spaltenagent: 'agent_id']} –