2015-04-29 10 views
5

Ho un problema con JPA e Hibernate e non riesco a risolverlo.ID incorporato e "colonna ripetuta nella mappatura per entità ..." eccezione

così, è il mio applicationContext.xml:

<context:component-scan base-package="com.abt.fiifootballmanager"> 
    <context:exclude-filter type="annotation" 
     expression="org.springframework.stereotype.Controller" /> 
</context:component-scan> 

<jdbc:embedded-database type="HSQL" id="dataSource" /> 

<bean 
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" 
    id="emf"> 
    <property name="packagesToScan" value="com.abt.fiifootballmanager.entity" /> 
    <property name="dataSource" ref="dataSource" /> 
    <property name="jpaProperties"> 
     <props> 
      <prop key="hibernate.show_sql">true</prop> 
      <prop key="hibernate.hbm2ddl.auto">create</prop> 
     </props> 
    </property> 
    <property name="persistenceProvider"> 
     <bean class="org.hibernate.jpa.HibernatePersistenceProvider" /> 
    </property> 
</bean> 

<tx:annotation-driven transaction-manager="transactionManager"/> 

<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager"> 
    <property name="dataSource" value="dataSource"/> 
</bean> 

Questa è la mia entità delle prestazioni:

package com.abt.fiifootballmanager.entity; 

import java.io.Serializable; 
import javax.persistence.*; 
import java.math.BigDecimal; 
import java.util.List; 

@Entity 
@Table(name="PERFORMANCES") 
@NamedQuery(name="Performance.findAll", query="SELECT p FROM Performance p") 
public class Performance implements Serializable { 
    private static final long serialVersionUID = 1L; 

    @EmbeddedId 
    private PerformancePK id; 

    @Column(name="RED_CARD") 
    private BigDecimal redCard; 

    @Column(name="YELLOW_CARD") 
    private BigDecimal yellowCard; 

    @OneToOne(mappedBy="performance") 
    private GoalkeepingPerformance goalkeepingPerformance; 

    @OneToMany(mappedBy="performance") 
    private List<OutfieldPerformance> outfieldPerformances; 

    @ManyToOne 
    @JoinColumn(name="MATCH_ID") 
    private Match match; 

    @ManyToOne 
    @JoinColumn(name="PLAYER_ID") 
    private Player player; 
    ...getters & setters } 

E questa è la mia classe id incorporato:

@Embeddable 
public class PerformancePK implements Serializable { 
    //default serial version id, required for serializable classes. 
    private static final long serialVersionUID = 1L; 

    @Column(name="MATCH_ID", insertable=false, updatable=false) 
    private long matchId; 

    @Column(name="PLAYER_ID", insertable=false, updatable=false) 
    private long playerId; 
    ... //getters and setters 

Quindi, queste sono le mie lezioni. Ma quando voglio correre la mia domanda mi vengono i prossimi eccezioni: 1.Error creating bean with name 'emf' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory

2. Repeated column in mapping for entity: com.abt.fiifootballmanager.entity.Performance column: MATCH_ID (should be mapped with insert="false" update="false") 

Penso che la prima eccezione è causata dal secondo. Quindi, perché ottengo "Colonna ripetuta nella mappatura per entità?". È una buona idea usare una classe di id incorporata ?.

risposta

9

I suoi due variabili match e player nella tua classe Performance sono mappati alle stesse colonne come matchId e playerId nel ID incorporato. Come dice l'errore, "dovrebbero essere mappati con insert =" false "update =" false "".

@ManyToOne 
@JoinColumn(name="MATCH_ID", insertable = false, updatable = false) 
private Match match; 

@ManyToOne 
@JoinColumn(name="PLAYER_ID", insertable = false, updatable = false) 
private Player player; 

Questo rende essenzialmente quei campi in sola lettura, in modo da Hibernate conosce solo per cambiare le MATCH_ID e PLAYER_ID colonne se vengono modificati i valori nel ID incorporato, ma non se sono cambiati i valori di match o player.

+0

posso cambiare come dici tu, ma non funzionano :(. – Rapidistul

+0

lo ha fatto dare lo stesso errore? Errore diverso? – forgivenson

+0

Lo stesso errore. – Rapidistul

0

Potrebbe essere possibile farlo utilizzando @EmbeddedId, ma potrebbe essere più semplice utilizzare l'annotazione @IdClass a livello di entità. È quindi possibile impostare la @Id annotazioni sulle @ManyToOne riferimenti direttamente:

@Entity 
@Table(name="PERFORMANCES") 
@IdClass(PerformancePK.class) 
@NamedQuery(name="Performance.findAll", query="SELECT p FROM Performance p") 
public class Performance implements Serializable { 

    static public class PerformancePK implements Serializable { 
     private long match; 
     private long player; 

     public PerformancePK() { 
     } 

     public PerformancePK(long match, long player) { 
      this.match = match; 
      this.player = player; 
     } 

     // TODO: implements equals() and hashCode() 
    } 

    @Id 
    @ManyToOne 
    @JoinColumn(name="MATCH_ID") 
    private Match match; 

    @Id 
    @ManyToOne 
    @JoinColumn(name="PLAYER_ID") 
    private Player player; 

    ... 
} 

ho definito la classe PerformancePK come una classe interna perché lo trovo conveniente, ma non dovrebbe essere così.

-1

Ho riscontrato lo stesso problema e ho risolto il problema modificando @Embeddedable/@EmbeddedId con @IdClass.

Le classi dovrebbe essere simile (i tralascio alcune informazioni):

@Entity 
@Table(name="PERFORMANCES") 
@IdClass(PerformancePK.class) 
public class Performance implements Serializable { 

    @Id 
    @Column(name="MATCH_ID") 
    private long matchId; 

    @Id 
    @Column(name="PLAYER_ID") 
    private long playerId; 

    @ManyToOne 
    @JoinColumn(name="MATCH_ID", insertable = false, updatable = false) 
    private Match match; 

    @ManyToOne 
    @JoinColumn(name="PLAYER_ID", insertable = false, updatable = false) 
    private Player player; 

    ...//getters, setters 
} 


public class PerformancePK implements Serializable { 

    private long matchId; 

    private long playerId; 

    ... //getters and setters 

    // !!! MANDATORY: override hashCode() and equals() here 
} 

Con questa costruzione, la struttura DB ancora lo stesso. Ulteriori informazioni su @IdClass usage.

Problemi correlati