2010-11-11 7 views
1

J'ai rencontré une erreur étrange avec JPA qui n'est pas spécifique au fournisseur de persistance. J'utilise JPA 2.0 et j'utilise un schéma généré. En bref: Le schéma généré inclut une table de jointure à trois colonnes, mais les instructions d'insertion générées traitent cette table comme si elle n'avait que deux colonnes.Instructions SQL incorrectes générées par JPA

Voici les correspondances:

@Entity 
@Table(name = "Game") 
public class MatchEntity implements Match, Serializable { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Long id; 

    @ManyToOne(targetEntity = ClubEntity.class) 
    private Club homeTeam; 

    @ManyToOne(targetEntity = ClubEntity.class) 
    private Club awayTeam; 

    @ManyToMany(targetEntity = PlayerEntity.class) 
    private Collection<Player> homeTeamPlayers; 

    @ManyToMany(targetEntity = PlayerEntity.class) 
    private Collection<Player> awayTeamPlayers; 

    private String location; 

    @Temporal(value = TemporalType.DATE) 
    @Column(name = "Match_Date") 
    private Date date; 

    /* constructor, getters and setters follow */ 
} 


@Entity 
@Table(name = "Club") 
public class ClubEntity implements Club, Serializable { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Long id; 

    private String name; 

    @OneToMany(fetch = FetchType.EAGER, targetEntity = PlayerEntity.class, 
    mappedBy = "club") 
    private Collection<Player> players = new ArrayList<Player>(); 

    private String fieldName; 

    private Boolean archived; 

    /* constructor, getters and setters follow */ 
} 

@Entity 
@Table(name = "PLAYER") 
public class PlayerEntity implements Player, Serializable { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Long id; 

    private String firstName; 

    private String surname; 

    @Temporal(value = TemporalType.DATE) 
    private Date birthDate; 

    @Column(name = "pos")  
    @Enumerated(EnumType.ORDINAL) 
    private Position position; 

    private Integer number; 

    private Boolean archived; 

    @ManyToOne(targetEntity = ClubEntity.class, fetch = FetchType.EAGER) 
    private Club club; 


    /* constructor, getters and setters follow */ 
} 

A partir de ces applications, le schéma suivant est créé:

create table Club (id bigint generated by default as identity (start with 1), archived bit, fieldName varchar(255) not null, name varchar(255) not null, primary key (id)) 
create table Game (id bigint generated by default as identity (start with 1), Match_Date date, location varchar(255), awayTeam_id bigint, homeTeam_id bigint, primary key (id)) 
create table Game_PLAYER (Game_id bigint not null, homeTeamPlayers_id bigint not null, awayTeamPlayers_id bigint not null) 
create table PLAYER (id bigint generated by default as identity (start with 1), archived bit, birthDate date, firstName varchar(255) not null, number integer, pos integer, surname varchar(255) not null, club_id bigint, primary key (id)) 
alter table Game add constraint FK21C0123B2A3B9E foreign key (homeTeam_id) references Club 
alter table Game add constraint FK21C012F5972EAF foreign key (awayTeam_id) references Club 
alter table Game_PLAYER add constraint FK267CF3AE6AE1D889 foreign key (Game_id) references Game 
alter table Game_PLAYER add constraint FK267CF3AED51EDECF foreign key (homeTeamPlayers_id) references PLAYER 
alter table Game_PLAYER add constraint FK267CF3AE6CBE869E foreign key (awayTeamPlayers_id) references PLAYER 
alter table PLAYER add constraint FK8CD18EE13F2C6C64 foreign key (club_id) references Club 

Cette ligne est importante - c'est la table de jointure.

create table Game_PLAYER (Game_id bigint not null, homeTeamPlayers_id bigint not null, awayTeamPlayers_id bigint not null) 

Lorsque je tente de conserver l'entité de jeu (MatchEntity.java), cela se produit:

insert into Game_PLAYER (Game_id, awayTeamPlayers_id) values (?, ?) 
Hibernate: insert into Game_PLAYER (Game_id, awayTeamPlayers_id) values (?, ?) 
binding '2' to parameter: 1 
binding '1' to parameter: 2 
reusing prepared statement 
insert into Game_PLAYER (Game_id, awayTeamPlayers_id) values (?, ?) 
Hibernate: insert into Game_PLAYER (Game_id, awayTeamPlayers_id) values (?, ?) 
binding '2' to parameter: 1 
binding '2' to parameter: 2 
done inserting collection: 2 rows inserted 
Inserting collection: [football.model.entities.MatchEntity.homeTeamPlayers#2] 
Executing batch size: 2 
about to close PreparedStatement (open PreparedStatements: 1, globally: 1) 
Could not execute JDBC batch update [insert into Game_PLAYER (Game_id, awayTeamPlayers_id) values (?, ?)] 

JPA tente d'insérer deux lignes à la table de jointure, chacune affectant seulement deux colonnes des trois .

Ce que j'ai essayé:

  • Se débarrasser des interfaces dans les applications tout à fait
  • Définition d'une table de jointure explicite
  • En utilisant OpenJPA au lieu de mise en veille prolongée

n'a pas non plus résoudre le problème.

modifier: code pour fetching impatient:

@Transactional(readOnly = true) 
    public Collection<Match> findAll() {   
     em.createQuery("SELECT m FROM MatchEntity m " 
      + "JOIN FETCH m.homeTeamPlayers", MatchEntity.class).getResultList(); 
     List<MatchEntity> rList = em.createQuery("SELECT m FROM MatchEntity m " 
      + "JOIN FETCH m.awayTeamPlayers", MatchEntity.class).getResultList(); 
     Collection<Match> result = new ArrayList<Match>(rList); 
     return result; 
    } 

Répondre

1

Peut-être vous avez besoin de jointure différent des tables pour homeTeamPlayers et awayTeamPlayers:

@ManyToMany(targetEntity = PlayerEntity.class) 
@JoinTable(name = "Game_HomeTeamPlayers") 
private Collection<Player> homeTeamPlayers; 

@ManyToMany(targetEntity = PlayerEntity.class) 
@JoinTable(name = "Game_AwayTeamPlayers") 
private Collection<Player> awayTeamPlayers; 
+0

J'ai essayé, mais avec deux tables de jointure, je reçois des instances en double de Classe MatchEntity sur select. Le nombre de doublons dépend du nombre de lignes dans les deux tables de jointure (nombre de joueurs dans le match). 3 lignes dans Game_AwayTeamPlayers et 4 lignes dans Game_HomeTeamPlayers provoquent le retour de 3 instances de ce jeu sur select, par exemple. – prasopes

+0

@stoupa: Peut-être avez-vous 'fetch = EAGER' sur ces relations? – axtavt

+0

@axtavt: Je n'ai pas envie d'aller les chercher, mais je les rejoins pour aller les chercher. Pourriez-vous s'il vous plaît me dire à quel point le fetching est en jeu? – prasopes

Questions connexes