2011-01-16 19 views
12

Sto usando Hibernate come provider di persistenza e modellazione miei entità con JPA 2.JPA 2: utilizzo multiplo colonna chiavi esterne

Ora una domanda si avvicinò e spero che tu mi possa aiutare.

Nella mia applicazione è possibile aprire una partita, creare gruppi di giocatori e spostarsi sulla mappa (tessere (2d)).

La mia definizioni di entità: Gioco:

@Entity 
public class Game implements Serializable { 
@Id 
@SequenceGenerator(name = "gen_gameid", sequenceName = "seq_gameid") 
@GeneratedValue(generator="gen_gameid") 
private long gameid; 

/** 
* Playing Characters. 
*/ 
@OneToMany(mappedBy = "game") 
private List<Character> characters; 
private int round = 0; 

@OneToMany(mappedBy="game") 
private List<Tile> tiles; 

@OneToMany(mappedBy="game") 
private List<Group> group; 

Tile (una tessera verrà creato da un modello e appartiene ad una sola partita):

@Entity @IdClass(TileId.class) 
public class Tile implements Serializable{ 
    private static final long serialVersionUID = 2039974286110729270L; 

    @Id 
    private int x; 

    @Id 
    private int y; 

    @Id @ManyToOne @JoinColumn(name="gameid") 
    private Game game; 

    @OneToOne(mappedBy="tile") 
    private Character character; 
} 

Carattere:

@ManyToOne 
@JoinColumn(name="gameid", referencedColumnName = "gameid") 
private Game game; 

@ManyToOne 
@JoinColumns({ 
    @JoinColumn(name="groupgameid", referencedColumnName = "gameid"), 
    @JoinColumn(name="groupTag", referencedColumnName = "grouptag") 
}) 
private Group group; 

    @OneToOne 
    @JoinColumns({  
     @JoinColumn(name = "x", referencedColumnName = "x"), 
     @JoinColumn(name = "y", referencedColumnName = "y"), 
     @JoinColumn(name = "tilegameid", referencedColumnName = "gameid") 
    }) 
    private Tile tile; 

Come puoi vedere ho dovuto rinominare la colonna Gameid in groupgameid e tilegam eid. Questo non è molto carino perché avrei bisogno del gameid nel personaggio solo una volta. Per contrassegnare le colonne fk nel carattere da tile e group con insertable = false, updateable = false consentirà la generazione sql, ma non posso modificare/impostare questi valori.

Certo, potrei introdurre un pk artificiale in gruppo e piastrella, ma avrei bisogno di più join.

JPA ha appena limitato che devo consentire alla colonna Gameid più di una volta con altri nomi? O il mio design non è ottimale?

In attesa di feedback e grazie in anticipo. saluti Markus

PS (edit): Al momento ho lasciato che lo Shema generare da Hibernate in fase di avvio fino al mio modello è completo. Ma qui è lo Shema generato (bit semplificato e tagliato fuori alcuni campi non importanti):

CREATE TABLE Character 
(
    charid bigint NOT NULL, 
    gameid bigint, 
    grouptag character varying(255), 
    x integer, 
    y integer, 
    CONSTRAINT hero_pkey PRIMARY KEY (charid), 
    CONSTRAINT fkd4addb09308bc3b822441a FOREIGN KEY (gameid) 
    REFERENCES game (gameid) MATCH SIMPLE 
    ON UPDATE NO ACTION ON DELETE NO ACTION, 
    CONSTRAINT fkd4addb093091cb6522441a FOREIGN KEY (gameid, x, y) 
    REFERENCES tile (gameid, x, y) MATCH SIMPLE 
    ON UPDATE NO ACTION ON DELETE NO ACTION, 
    CONSTRAINT fkd4addb09c018f3ae22441a FOREIGN KEY (gameid, grouptag) 
    REFERENCES gamegroup (gameid, grouptag) MATCH SIMPLE 
    ON UPDATE NO ACTION ON DELETE NO ACTION 
) 

CREATE TABLE tile (
    x integer NOT NULL, 
    y integer NOT NULL, 
    gameid bigint NOT NULL, 
    CONSTRAINT tile_pkey PRIMARY KEY (gameid, x, y), 
    CONSTRAINT fk27c6ce308bc3b8 FOREIGN KEY (gameid) 
    REFERENCES game (gameid) MATCH SIMPLE 
    ON UPDATE NO ACTION ON DELETE NO ACTION) 

CREATE TABLE gamegroup 
(
    grouptag character varying(255) NOT NULL, 
    gameid bigint NOT NULL, 
    CONSTRAINT gamegroup_pkey PRIMARY KEY (gameid, grouptag), 
    CONSTRAINT fk3c1c51cd308bc3b8 FOREIGN KEY (gameid) 
    REFERENCES game (gameid) MATCH SIMPLE 
    ON UPDATE NO ACTION ON DELETE NO ACTION 
) 

PS 2: Ho già giocato con , insertable = false, updatable = false. Ad esempio quando cambio i JoinColumns gruppo di:

@ManyToOne 
@JoinColumns({ 
    @JoinColumn(name="gameid", referencedColumnName = "gameid", insertable = false, updatable = false), 
    @JoinColumn(name="groupTag", referencedColumnName = "grouptag") 
}) 
private Group group; 

ottengo un errore che la miscelazione non è consentito: causato da: org.hibernate.AnnotationException: Miscelazione colonne inseribili inseribili e non in una struttura non è consentito : net.hq.model.Charactergroup

Quando eseguo sia insertable = false, non sono più in grado di impostare il tag di gruppo. GroupTag rimane vuoto dopo l'inserimento e viene impostato gameid. : -/

il mio modo di aggiungere un carattere a un gruppo:

// Create game 
Game game = new Game(); 
game.addCharacter(max); 
em.persist(game); 

// Group 
Group heroGroup = new Group(game, "HEROES"); 
heroGroup.addCharacter(max); 
em.persist(game); 

Metodo della classe Gruppo:

public void addCharacter(Character character){ 
    if(this.characters == null) 
     this.characters = new ArrayList<Character>(); 

    this.characters.add(character); 
    character.setGroup(this); 
} 
+0

Sarei molto più facile per aiutare se si potesse fornire schema DB correlate e specificare l'annotazione @Table delle classi. – Osw

+0

pubblicato alla fine della mia domanda. Saluti. – mkuff

risposta

3

Sei sicuro non è possibile utilizzare insertable = false, updateable = false per questi @JoinColumn s?

Per quanto ho capito, è possibile inizializzare gameid una volta impostando game proprietà, e dopo che non hai bisogno di cambiare da quando Tile s e Group s appartengono alla stessa Game.

+0

Sì, è vero. Ma sembra che non mi sia permesso mescolare gli attributi JoinColums. Spiegazione in PS 2. Saluti – mkuff

7

quello che devi fare questo:

@ManyToOne 
@JoinColumns({ 
    @JoinColumn(name="gameid", referencedColumnName = "gameid", insertable = false, updatable = false), 
    @JoinColumn(name="groupTag", referencedColumnName = "grouptag", insertable = false, updatable = false) 
}) 
private Group group; 
+0

Grazie a Sanama Na che mi ha avvicinato molto. Devo cambiare per usare le parentesi quadre poiché JoinColumns si aspettava un array. – bigMC28

Problemi correlati