JPA - 创建了错误的表

时间:2011-08-04 16:35:03

标签: java hibernate postgresql jpa

鉴于这些实体:

class SportTeam {
   @Id
   @GeneratedValue
   long id;
   @OneToMany
   private Set<PLayer> players;
   @OneToMany
   private Set<Player> stars;
}
// A sport team can have multiple players and some of those players can be stars.

class Player {
   @Id
   @GeneratedValue
   long id;
   (...)
}

这是Hibernate生成的DDL:

CREATE TABLE sportteam
(
  id bigint NOT NULL,
  (...)
  CONSTRAINT sportteam_pkey PRIMARY KEY (id)
)

CREATE TABLE sportteam_player
(
  sportteam_id bigint NOT NULL,
  player_id bigint NOT NULL,
  star_id bigint NOT NULL,
  CONSTRAINT sportteam_player_pkey PRIMARY KEY (sportteam_id, star_id),
  CONSTRAINT fk6cf55c6645d973bc FOREIGN KEY (player_id)
  REFERENCES player (id) MATCH SIMPLE
  ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT fk6cf55c66ca1af8b8 FOREIGN KEY (star_id)
  REFERENCES player (id) MATCH SIMPLE
  ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT sportteam_player_star_id_key UNIQUE (star_id),
  CONSTRAINT sportteam_player_player_id_key UNIQUE (player_id)
)    


CREATE TABLE player
(
   id bigint NOT NULL,
   (...)
   CONSTRAINT player_pkey PRIMARY KEY (id)
)

我希望sportteam_player看起来像这样:

CREATE TABLE sportteam_player
(
  sportteam_id bigint NOT NULL,
  player_id bigint NOT NULL,
  is_star boolean DEFAULT 'FALSE',
  CONSTRAINT sportteam_player_pkey PRIMARY KEY (sportteam_id, player_id),
  CONSTRAINT fk6cf55c6645d973bc FOREIGN KEY (player_id)
  REFERENCES player (id) MATCH SIMPLE
  ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT fk6cf55c66ca1af8b8 FOREIGN KEY (sportteam_id)
  REFERENCES sportteam (id) MATCH SIMPLE
  ON UPDATE NO ACTION ON DELETE NO ACTION
)    

我该怎么办?

1 个答案:

答案 0 :(得分:4)

对这样的JPA关系进行建模是不可行的。您假设Team-to-Star是关系数据库意义上的一对多关系。它肯定是某种刻板印象的关系,但它是基于一个明星与否的球员的属性。所以:

class Player {
  @Id
  @GeneratedValue
  long id;
  @Column(name = “is_star”, columnDefinition="boolean default false")
  boolean star;
  (...)
}

class SportTeam {
  @Id
  @GeneratedValue
  long id;
  @OneToMany
  private Set<PLayer> players;

  public Collection<Player> getStars() {
    // return your stars here, filter through players.
    // if you want you can do caching, but remember to set the field to @Transient
    // so that Hibernate does not think, it could be a relation
  }
}

我为什么要这样做?在SportTeam中,无论如何你已经加载了所有的玩家。没理由通过数据库这样做。作为明星是明星的财产,如果你需要SportTeam课程中的列表,它只是现有玩家的不同观点。