created_by字段上的DuplicateMappingException

时间:2017-10-22 11:27:06

标签: java mysql hibernate spring-boot spring-data-jpa

我有2个表employeeemployee_document。这是两个表的mysql查询 -

CREATE TABLE employee (
  id int(11) unsigned NOT NULL,
  name varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  email varchar(50) COLLATE utf8_unicode_ci NOT NULL,
  password_hash varchar(100) COLLATE utf8_unicode_ci NOT NULL,
  status int(11) NOT NULL,
  creation_date bigint(20) NOT NULL,
  created_by int(11) DEFAULT NULL,
  update_date bigint(20) NOT NULL,
  updated_by int(11) DEFAULT NULL,
  PRIMARY KEY (id),
  UNIQUE KEY email (email)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

CREATE TABLE employee_document (
  id int(11) unsigned NOT NULL AUTO_INCREMENT,
  employee_id int(11) unsigned NOT NULL,
  file_id int(11) unsigned NOT NULL,
  document_type varchar(50) COLLATE utf8_unicode_ci DEFAULT '',
  status int(11) DEFAULT NULL,
  creation_date bigint(20) DEFAULT NULL,
  created_by int(11) unsigned NOT NULL,
  update_date bigint(20) DEFAULT NULL,
  updated_by int(11) unsigned NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

在我的春季启动项目中,我将hibernate与JPA Data一起使用。以下是这些表的java解释。

@MappedSuperclass
public abstract class AbstractTimestampEntity {

    @Transient
    Logger log = LoggerFactory.getLogger(AbstractTimestampEntity.class);

    @Column(name = "creation_date", nullable = false, updatable=false)
    private Long creationDate;

    @Column(name = "update_date", nullable = false)
    private Long updateDate;

    @PrePersist
    protected void onCreate() {
        log.debug("onCreate");
        updateDate = creationDate = System.currentTimeMillis();
    }

    @PreUpdate
    protected void onUpdate() {
        log.debug("onUpdate");
        updateDate = System.currentTimeMillis();
    }
}

@Entity
@Table(name = "employee")
public class Employee extends AbstractTimestampEntity implements Serializable {
    private static final long serialVersionUID = 1L;

    public static final Integer STATUS_INACTIVE = 0;
    public static final Integer STATUS_ACTIVE = 1;
    public static final Integer STATUS_ARCHIVED = -1;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    public Integer id;

    @Column(name = "name", nullable = false)
    public String name;

    @Email
    @Column(name = "email", nullable = false, unique = true)
    public String email;

    @JsonIgnore
    @Column(name = "password_hash", nullable = false)
    public String passwordHash;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "employee", fetch = FetchType.EAGER)
    private Set<EmployeeDocument> documents;

    @Max(1)
    @Min(-1)
    @Column(name = "status", nullable = false )
    public Integer status;

    @Column(name = "created_by", updatable = false)
    public Integer createdById;

    @Column(name = "updated_by")
    public Integer updatedById;
}

@Entity
@Table(name = "employee_document")
public class EmployeeDocument extends AbstractTimestampEntity implements Serializable {
    private static final long serialVersionUID = 1L;

    @Transient
    public static final Integer STATUS_INACTIVE = 0;
    @Transient
    public static final Integer STATUS_ACTIVE = 1;
    @Transient
    public static final Integer STATUS_ARCHIVED = -1;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    public Integer id;

    @JsonIgnore
    @ManyToOne
    @JoinColumn(name = "employee_id", nullable = false)
    public Employee employee;

    @OneToOne
    @JoinColumn(name = "file_id")
    public EmployeeFile employeeFile;

    @Max(1)
    @Min(-1)
    @Column(name = "status", nullable = false )
    public Integer status;

    @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinColumn(name = "created_by", updatable = false)
    @JsonBackReference
    public Employee createdBy;

    @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinColumn(name = "updated_by")
    @JsonBackReference
    public Employee updatedBy;
}

此代码未执行,应用无法启动并抛出DuplicateMappingException。这是完整的异常堆栈 -

org.hibernate.DuplicateMappingException: Table [employee_document] contains physical column name [created_by] referred to by multiple physical column names: [createdBy], [created_by]
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl$TableColumnNameBinding.bindPhysicalToLogical(InFlightMetadataCollectorImpl.java:922)
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl$TableColumnNameBinding.addBinding(InFlightMetadataCollectorImpl.java:891)
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.addColumnNameBinding(InFlightMetadataCollectorImpl.java:961)
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.addColumnNameBinding(InFlightMetadataCollectorImpl.java:942)
at org.hibernate.cfg.Ejb3Column.addColumnBinding(Ejb3Column.java:407)
at org.hibernate.cfg.Ejb3Column.linkWithValue(Ejb3Column.java:369)
at org.hibernate.cfg.annotations.SimpleValueBinder.linkWithValue(SimpleValueBinder.java:431)
at org.hibernate.cfg.annotations.SimpleValueBinder.make(SimpleValueBinder.java:407)
at org.hibernate.cfg.annotations.PropertyBinder.makePropertyAndValue(PropertyBinder.java:187)
at org.hibernate.cfg.annotations.PropertyBinder.makePropertyValueAndBind(PropertyBinder.java:199)
at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:2225)
at org.hibernate.cfg.AnnotationBinder.processIdPropertiesIfNotAlready(AnnotationBinder.java:911)
at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:738)
at org.hibernate.boot.model.source.internal.annotations.AnnotationMetadataSourceProcessorImpl.processEntityHierarchies(AnnotationMetadataSourceProcessorImpl.java:245)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess$1.processEntityHierarchies(MetadataBuildingProcess.java:222)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:265)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:847)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:874)
at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:60)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:353)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:373)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:362)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1687)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624)
... 19 common frames omitted 

我做错了什么?提前谢谢。

1 个答案:

答案 0 :(得分:0)

您尝试从EmployeeDocument引用Empolyee三次,但只有一个是主键。其他两个由非主键列引用,您还需要使用referencedColumnName选项才能使其工作:

@JsonIgnore
@ManyToOne
@JoinColumn(name = "employee_id", nullable = false)
public Employee employee;


@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "created_by", referencedColumnName="created_by", updatable = false)
@JsonBackReference
public Employee createdBy;

@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinColumn(name = "updated_by". , referencedColumnName="updated_by")
@JsonBackReference
public Employee updatedBy;