java 嵌入的 id 和“实体映射中的重复列...”异常

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29952386/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 16:10:16  来源:igfitidea点击:

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

javaspringhibernatejpa

提问by Rapidistul

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

我在使用 JPA 和 Hibernate 时遇到问题,但无法解决。

So, it is my applicationContext.xml:

所以,这是我的 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:

这是我的 Performance 实体:

 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:

这是我嵌入的 id 类:

@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

所以,这些是我的课程。但是当我想运行我的应用程序时,我得到了下一个例外: 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?.

我认为第一个例外是由第二个引起的。那么,为什么我会得到“实体映射中的重复列?”。使用嵌入式 id 类是个好主意吗?。

回答by forgivenson

Your two variables matchand playerin your Performanceclass are mapped to the same columns as matchIdand playerIdin the embedded ID. As the error says, they "should be mapped with insert="false" update="false"".

你的两个变量match,并player在你的Performance类被映射到相同的列matchIdplayerId嵌入式ID。正如错误所说,它们“应该用 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_IDand PLAYER_IDcolumns if the values in the embedded ID are changed, but not if the values of matchor playerare changed.

这实质上使这些字段成为只读的,因此 Hibernate 只知道在嵌入 ID 中的值更改时更改MATCH_IDPLAYER_ID列,而不知道match或的值player更改时更改。

回答by Eugene

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

我遇到了同样的问题,并通过将@Embeddedable/更改@EmbeddedId@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.

通过这种结构,您的数据库结构仍然相同。有关@IdClass 用法的更多信息。

回答by David Levesque

It may be possible to do this using @EmbeddedId, but it may be easier to use the @IdClassannotation at the entity level. You can then set the @Idannotation on the @ManyToOnereferences directly:

可以使用 来执行此操作@EmbeddedId,但@IdClass在实体级别使用注释可能更容易。然后,您可以直接@Id@ManyToOne引用上设置注释:

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

    ...
}

I have defined the PerformancePK class as an inner class because I find it convenient, but it doesn't have to be.

我已将 PerformancePK 类定义为内部类,因为我觉得它很方便,但并非必须如此。