首页 > 解决方案 > Spring继承,多对多,实体映射中的重复列

问题描述

类图

嗨,我正在尝试映射从类 Person 扩展的两个类 Employee 和 Manager 之间的多对多关系。问题是两个类具有相同的 id,因为它们从同一个超类扩展而来。这就是为什么我得到例外

... Repeated column in mapping for entity ...

请通过保持继承设计来帮助解决这个问题。

注意:从 relashionship 生成的 Class 具有额外的属性。

Java 类

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorType;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name = "PERSON")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
    name="discriminator",
    discriminatorType=DiscriminatorType.STRING
)
@DiscriminatorValue(value="P")
public class Person {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "PERSON_ID")
    protected int personId;
    @Column(name = "PERSON_FIRST_NAME")
    protected String personFirstName;
    @Column(name = "PERSON_LAST_NAME")
    protected String personLastName;
    @Column(name = "PERSON_EMAIL")
    protected String personEmail;
    @Column(name = "PERSON_IMAGE")
    protected String personImage;

    // Constructors and Getter/Setter methods,
    public Person() {
    }

    /**
     * @param personId
     * @param personFirstName
     * @param personLastName
     * @param personEmail
     * @param personImage
     */
    public Person(String personFirstName, String personLastName, String personEmail, String personImage) {
        this.personFirstName = personFirstName;
        this.personLastName = personLastName;
        this.personEmail = personEmail;
        this.personImage = personImage;
    }

    public int getPersonId() {
        return personId;
    }

    public void setPersonId(int personId) {
        this.personId = personId;
    }

    public String getPersonFirstName() {
        return personFirstName;
    }

    public void setPersonFirstName(String personFirstName) {
        this.personFirstName = personFirstName;
    }

    public String getPersonLastName() {
        return personLastName;
    }

    public void setPersonLastName(String personLastName) {
        this.personLastName = personLastName;
    }

    public String getPersonEmail() {
        return personEmail;
    }

    public void setPersonEmail(String personEmail) {
        this.personEmail = personEmail;
    }

    public String getPersonImage() {
        return personImage;
    }

    public void setPersonImage(String personImage) {
        this.personImage = personImage;
    }

}

经理

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;


@Entity
@Table(name="PERSON")
@DiscriminatorValue("M")
public class Manager extends Person implements Serializable{

    @Column(name="Budget")
    private double budget;

    @OneToMany( fetch = FetchType.LAZY, mappedBy="manager",
            cascade=CascadeType.ALL)
    private List<Meeting> listAppointment;

    public Manager() {
        super();
    }


    public Manager(String personFirstName, String personLastName, String personEmail, String personImage, double budget) {
        super(personFirstName, personLastName, personEmail, personImage);
        this.budget=budget;
    }

    public double getBudget() {
        return budget;
    }


    public void setBudget(double budget) {
        this.budget = budget;
    }

    //meeting
    public List<Meeting> getListAppointment() {
        if (listAppointment == null)
            listAppointment = new ArrayList<>();
        return listAppointment;
    }

    public Iterator<Meeting> getIteratorAppointment() {
        if (listAppointment == null)
            listAppointment = new ArrayList<>();
        return listAppointment.iterator();
    }


    public void setListAppointment(List<Meeting> newListAppointment) {
        removeAllAppointment();
        for (Iterator<Meeting> iter = newListAppointment.iterator(); iter.hasNext();)
            addAppointment(iter.next());
    }

    public void addAppointment(Meeting newAppointment) {
        if (newAppointment == null)
            return;
        if (this.listAppointment == null)
            this.listAppointment = new ArrayList<>();
        if (!this.listAppointment.contains(newAppointment)) {
            this.listAppointment.add(newAppointment);
            newAppointment.setDoctor(this);
        }
    }

    public void removeAppointment(Meeting oldAppointment) {
        if (oldAppointment == null)
            return;
        if (this.listAppointment != null && this.listAppointment.contains(oldAppointment)) {
            this.listAppointment.remove(oldAppointment);
            oldAppointment.setDoctor(null);
        }
    }

    public void removeAllAppointment() {
        if (listAppointment != null) {
            Meeting oldAppointment;
            for (Iterator<Meeting> iter = getIteratorAppointment(); iter.hasNext();) {
                oldAppointment = iter.next();
                iter.remove();
                oldAppointment.setDoctor(null);
            }
        }
    }
    // End Meeting

}

员工

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;


@Entity
@Table(name = "PERSON")
@DiscriminatorValue("E")
public class Employee extends Person implements Serializable {


    @OneToMany( fetch = FetchType.LAZY, mappedBy="employee",
            cascade=CascadeType.ALL)
    private List<Meeting> listAppointment;

    public Employee() {
        super();
    }

    public Employee(String personFirstName, String personLastName, String personEmail, String personImage) {
        this.personFirstName = personFirstName;
        this.personLastName = personLastName;
        this.personEmail = personEmail;
        this.personImage = personImage;
    }

}

会议.java

@Entity
@Table(name = "MEETING")
public class Meeting implements Serializable{
@Id
@GeneratedValue
@Column(name = "MEETING_ID")
private long id;

@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "PERSON_ID") 
private Manager manager;

@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "PERSON_ID")  
private Employee employee;

// additional fields
private boolean activated;
private Date registeredDate;

public Meeting() {
}

public Meeting(Manager manager, Employee employee) {
    this.manager = manager;
    this.employee = employee;
    this.id= Long.parseLong(String.valueOf(manager.getPersonId()).concat(String.valueOf(employee.getPersonId())));
}

Java 异常

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1710) ~[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:583) ~[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:502) ~[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:312) ~[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228) ~[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:310) ~[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1085) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:858) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549) ~[spring-context-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:752) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:388) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:327) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1246) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1234) [spring-boot-2.0.0.RELEASE.jar:2.0.0.RELEASE]
    at org.gestion.GestionCliniqueApplication.main(GestionCliniqueApplication.java:10) [classes/:na]
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:970) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:895) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
    at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:57) ~[spring-orm-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) ~[spring-orm-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:388) ~[spring-orm-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:377) ~[spring-orm-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341) ~[spring-orm-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1769) ~[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1706) ~[spring-beans-5.0.4.RELEASE.jar:5.0.4.RELEASE]
    ... 15 common frames omitted
Caused by: org.hibernate.MappingException: Repeated column in mapping for entity: org.gestion.modele.Meeting column: person_id (should be mapped with insert="false" update="false")
    at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:835) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
    at org.hibernate.mapping.PersistentClass.checkPropertyColumnDuplication(PersistentClass.java:853) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
    at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:875) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
    at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:607) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
    at org.hibernate.mapping.RootClass.validate(RootClass.java:265) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
    at org.hibernate.boot.internal.MetadataImpl.validate(MetadataImpl.java:329) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
    at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:459) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:892) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
    ... 22 common frames omitted

标签: javaspringhibernateinheritancemany-to-many

解决方案


首先,我认为您应该更改类 Person 的 InheritanceType

@Inheritance(strategy = InheritanceType.JOINED)

其次,为 Employee 和 Manager 类添加 id。


推荐阅读