Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Embedded id and "repeated column in mapping for entity..." exception

I have a problem with JPA and Hibernate and I fail to solve it.

So, it is my 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>

This is my Performance entity:

 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 }

And this is my embedded id class:

@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

So, these are my classes. But when I want to run my application I get the next exceptions: 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")

I think that the first exception it's caused by the second. So, why I get "Repeated column in mapping for entity?". It's a good idea to use an embedded id class?.

like image 855
Rapidistul Avatar asked Apr 29 '15 19:04

Rapidistul


2 Answers

Your two variables match and player in your Performance class are mapped to the same columns as matchId and playerId in the embedded ID. As the error says, they "should be mapped with 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;

This essentially makes those fields readonly, so Hibernate knows only to change the MATCH_ID and PLAYER_ID columns if the values in the embedded ID are changed, but not if the values of match or player are changed.

like image 160
forgivenson Avatar answered Nov 15 '22 01:11

forgivenson


I encountered the same problem, and solved it by changing @Embeddedable/@EmbeddedId with @IdClass.

Your classes should look like (i omit some info):

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

With this construction, your DB structure still the same. More information about @IdClass usage.

like image 3
Eugene Avatar answered Nov 14 '22 23:11

Eugene