JPA 2: использование нескольких столбцов во внешних ключах

Я использую Hibernate в качестве поставщика сохраняемости и моделирую свои сущности с помощью JPA 2.

Теперь возник вопрос, и я надеюсь, что вы можете мне помочь.

В моем приложении вы можете открывать игру, создавать в ней группы игроков и ходить по карте (плитки (2d)).

Сначала мои определения сущностей: Игра:

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

Плитка (тайл будет создан из шаблона и принадлежит только одной игре):

@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;
}

Персонаж:

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

Как видите, мне пришлось переименовать столбец gameid в groupgameid и tilegameid. Это не очень красиво, потому что мне понадобится gameid в персонаже только один раз. Чтобы пометить столбцы fk в символе из плитки и группы с помощью insertable = false, updateable = false разрешит создание sql, но я не могу изменить / установить эти значения.

Конечно, я мог бы ввести искусственный pk в группу и плитку, но мне нужно больше объединений.

Ограничена ли JPA тем, что я должен разрешить столбец gameid более одного раза с другими именами? Или мой дизайн не оптимален?

Жду ваших отзывов и заранее благодарим. Привет Маркус

PS (править): В настоящий момент я позволяю схеме генерировать спящий режим при запуске, пока моя модель не будет завершена. Но вот сгенерированная схема (немного упрощена и вырезаны некоторые неважные поля):

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: Я уже играл с , insertable = false, updatable = false . Например, когда я меняю группу JoinColumns на:

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

, я получаю сообщение об ошибке, что смешивание запрещено: Вызвано: org.hibernate.AnnotationException: Смешивание вставляемых и не вставляемых столбцов в свойстве запрещено: net.hq.model.Charactergroup

Когда я делаю оба insertable = false, я больше не могу установить групповой тег. GroupTag остается пустым после вставки и установки gameid. : - /

Способ добавления персонажа в группу:

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

Метод в классе группы:

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

    this.characters.add(character);
    character.setGroup(this);
}
14
задан Sean Patrick Floyd 16 January 2011 в 15:21
поделиться