【问题标题】:How to make unidirectional @oneToMany relationship for 2 tables using JPA and Hibernate如何使用 JPA 和 Hibernate 为 2 个表建立单向 @oneToMany 关系
【发布时间】:2018-04-03 21:53:22
【问题描述】:

我的项目基于 spring boot、Thymeleaf、mysql、html 和 Jquery。我试图在 maintable 中创建一个单向的 @oneToMany 关系,但它只会产生类似的错误

2017-10-23 16:17:49.908 ERROR 18724 --- [           main] o.s.boot.SpringApplication               : Application startup failed
 
 org.springframework.beans.factory.BeanCreationException: Error
 creating bean with name 'entityManagerFactory' defined in class path
 resource
 [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]:
 Invocation of init method failed; nested exception is
 org.hibernate.AnnotationException: **Unable to map collection
 com.vfraternity.process.entity.EntPropertyMaster.blockListPropSub**   at
 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1702)
 ~[spring-beans-5.0.0.RC4.jar:5.0.0.RC4]   at
 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:583)
 ~[spring-beans-5.0.0.RC4.jar:5.0.0.RC4]   at
 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:502)
 ~[spring-beans-5.0.0.RC4.jar:5.0.0.RC4]   at
 org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:312)
 ~[spring-beans-5.0.0.RC4.jar:5.0.0.RC4]   at
 org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
 ~[spring-beans-5.0.0.RC4.jar:5.0.0.RC4]   at
 org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:310)
 ~[spring-beans-5.0.0.RC4.jar:5.0.0.RC4]   at
 org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200)
 ~[spring-beans-5.0.0.RC4.jar:5.0.0.RC4]   at
 org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1083)
 ~[spring-context-5.0.0.RC4.jar:5.0.0.RC4]     at
 org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:858)
 ~[spring-context-5.0.0.RC4.jar:5.0.0.RC4]     at
 org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549)
 ~[spring-context-5.0.0.RC4.jar:5.0.0.RC4]     at
 org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:122)
 ~[spring-boot-2.0.0.M4.jar:2.0.0.M4]  at
 org.springframework.boot.SpringApplication.refresh(SpringApplication.java:750)
 [spring-boot-2.0.0.M4.jar:2.0.0.M4]   at
 org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:386)
 [spring-boot-2.0.0.M4.jar:2.0.0.M4]   at
 org.springframework.boot.SpringApplication.run(SpringApplication.java:327)
 [spring-boot-2.0.0.M4.jar:2.0.0.M4]   at
 org.springframework.boot.SpringApplication.run(SpringApplication.java:1245)
 [spring-boot-2.0.0.M4.jar:2.0.0.M4]   at
 org.springframework.boot.SpringApplication.run(SpringApplication.java:1233)
 [spring-boot-2.0.0.M4.jar:2.0.0.M4]   at
 com.vfraternity.VfSpringBootMain.main(VfSpringBootMain.java:12)
 [classes/:na] Caused by: org.hibernate.AnnotationException: Unable to
 map collection
 com.vfraternity.process.entity.EntPropertyMaster.blockListPropSub     at
 org.hibernate.cfg.annotations.CollectionBinder.bindCollectionSecondPass(CollectionBinder.java:1604)
 ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]   at
 org.hibernate.cfg.annotations.CollectionBinder.bindOneToManySecondPass(CollectionBinder.java:871)
 ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]   at
 org.hibernate.cfg.annotations.CollectionBinder.bindStarToManySecondPass(CollectionBinder.java:786)
 ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]   at
 org.hibernate.cfg.annotations.CollectionBinder$1.secondPass(CollectionBinder.java:725)
 ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]   at
 org.hibernate.cfg.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:54)
 ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]   at
 org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1621)
 ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]   at
 org.hibernate.boot.internal.InFlightMetadataCollectorImpl.processSecondPasses(InFlightMetadataCollectorImpl.java:1589)
 ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]   at
 org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:278)
 ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]   at
 org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:858)
 ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]   at
 org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:885)
 ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]   at
 org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:57)
 ~[spring-orm-5.0.0.RC4.jar:5.0.0.RC4]     at
 org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:358)
 ~[spring-orm-5.0.0.RC4.jar:5.0.0.RC4]     at
 org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:384)
 ~[spring-orm-5.0.0.RC4.jar:5.0.0.RC4]     at
 org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:373)
 ~[spring-orm-5.0.0.RC4.jar:5.0.0.RC4]     at
 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods AbstractAutowireCapableBeanFactory.java:1761)
 ~[spring-beans-5.0.0.RC4.jar:5.0.0.RC4]   at
 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1698)
 ~[spring-beans-5.0.0.RC4.jar:5.0.0.RC4]   ... 16 common frames omitted
 Caused by: org.hibernate.cfg.RecoverableException: Unable to find
 column with logical name: propertysubpk in
 org.hibernate.mapping.Table(property_master) and its related
 supertables and secondary tables  at
 org.hibernate.cfg.Ejb3JoinColumn.checkReferencedColumnsType(Ejb3JoinColumn.java:831)
 ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]   at
 org.hibernate.cfg.BinderHelper.createSyntheticPropertyReference(BinderHelper.java:243)
 ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]   at
 org.hibernate.cfg.annotations.CollectionBinder.bindCollectionSecondPass(CollectionBinder.java:1594)
 ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]   ... 31 common frames
 omitted Caused by: org.hibernate.MappingException: Unable to find
 column with logical name: propertysubpk in
 org.hibernate.mapping.Table(property_master) and its related
 supertables and secondary tables  at
 org.hibernate.cfg.Ejb3JoinColumn.checkReferencedColumnsType(Ejb3JoinColumn.java:826)
 ~[hibernate-core-5.2.10.Final.jar:5.2.10.Final]   ... 33 common frames
 omitted

我尝试使用单向实现

@OneToMany(cascade=CascadeType.ALL)
@JoinColumn(name="propertysubfkid", referencedColumnName="propertysubpk")
private List<EntPropertySub> blockListPropSub = newArrayList<EntPropertySub>();

但它只会产生错误... 这是我的完整代码..

**EntPropertyMaster** 

package com.vfraternity.process.entity;

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

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Version;
import javax.validation.constraints.NotNull;


@Entity
@Table(name="Property_Master")
public class EntPropertyMaster implements Serializable{

/**
 * 
 */
private static final long serialVersionUID = 6162594257264775391L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="propertyid")
private int property_id;
@NotNull
private String property_name;
@NotNull
private String address1;
@NotNull
@Column(columnDefinition="varchar(15) default'None'")
private String address2;
@NotNull
private String city;
@NotNull
private String state;
@NotNull
private String country;
@NotNull
private int zipcode;

@OneToMany(cascade=CascadeType.ALL)
@JoinColumn(name="propertysubfkid", referencedColumnName="propertysubpk")
private List<EntPropertySub> blockListPropSub = new ArrayList<EntPropertySub>();

@Version
private int version;
private Boolean is_active;
private String created_by;
private Date created_ts;
private String modified_by;
private Date modified_ts;
private String approved_by;
private Date approved_ts;





public EntPropertyMaster() {
    
}
//Getter Setter
public int getProperty_id() {
    return property_id;
}
public void setProperty_id(int property_id) {
    this.property_id = property_id;
}
public String getProperty_name() {
    return property_name;
}
public void setProperty_name(String property_name) {
    this.property_name = property_name;
}
public String getAddress1() {
    return address1;
}
public void setAddress1(String address1) {
    this.address1 = address1;
}
public String getAddress2() {
    return address2;
}
public void setAddress2(String address2) {
    this.address2 = address2;
}
public String getCity() {
    return city;
}
public void setCity(String city) {
    this.city = city;
}
public String getState() {
    return state;
}
public void setState(String state) {
    this.state = state;
}
public String getCountry() {
    return country;
}
public void setCountry(String country) {
    this.country = country;
}
public int getVersion() {
    return version;
}
public void setVersion(int version) {
    this.version = version;
}
public Boolean getIs_active() {
    return is_active;
}
public void setIs_active(Boolean is_active) {
    this.is_active = is_active;
}
public String getCreated_by() {
    return created_by;
}
public void setCreated_by(String created_by) {
    this.created_by = created_by;
}
public Date getCreated_ts() {
    return created_ts;
}
public void setCreated_ts(Date created_ts) {
    this.created_ts = created_ts;
}
public String getModified_by() {
    return modified_by;
}
public void setModified_by(String modified_by) {
    this.modified_by = modified_by;
}
public Date getModified_ts() {
    return modified_ts;
}
public void setModified_ts(Date modified_ts) {
    this.modified_ts = modified_ts;
}
public String getApproved_by() {
    return approved_by;
}
public void setApproved_by(String approved_by) {
    this.approved_by = approved_by;
}
public Date getApproved_ts() {
    return approved_ts;
}
public void setApproved_ts(Date approved_ts) {
    this.approved_ts = approved_ts;
}
public int getZipcode() {
    return zipcode;
}
public void setZipcode(int zipcode) {
    this.zipcode = zipcode;
}
public List<EntPropertySub> getBlockListPropSub() {
    return blockListPropSub;
}
public void setBlockListPropSub(List<EntPropertySub> blockListPropSub) {
    this.blockListPropSub = blockListPropSub;
}
}

/////////////////////////////////////// ////////////// EntPropertySub 包 com.vfraternity.process.entity;

import java.io.Serializable;
import java.util.Date;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Version;
import javax.validation.constraints.NotNull;

@Entity
@Table(name="propertysub")
public class EntPropertySub implements Serializable
{

/**
 * 
 */
private static final long serialVersionUID = 810618405796553525L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="propertysubpk")
private int propertySub_pk;

@NotNull
private String blockname;
@NotNull
private int floors;
@NotNull
private String flatstart;
private String flatend;

@Version
private int version;
private Boolean is_active;
private String created_by;
private Date created_ts;
private String modified_by;
private Date modified_ts;
private String approved_by;
private Date approved_ts;

public EntPropertySub() {
    
}


//Getter Setter
public int getPropertySub_pk() {
    return propertySub_pk;
}
public void setPropertySub_pk(int propertySub_pk) {
    this.propertySub_pk = propertySub_pk;
}
public String getBlockname() {
    return blockname;
}
public void setBlockname(String blockname) {
    this.blockname = blockname;
}
public int getFloors() {
    return floors;
}
public void setFloors(int floors) {
    this.floors = floors;
}
public String getFlatstart() {
    return flatstart;
}
public void setFlatstart(String flatstart) {
    this.flatstart = flatstart;
}
public String getFlatend() {
    return flatend;
}
public void setFlatend(String flatend) {
    this.flatend = flatend;
}
public int getVersion() {
    return version;
}
public void setVersion(int version) {
    this.version = version;
}
public Boolean getIs_active() {
    return is_active;
}
public void setIs_active(Boolean is_active) {
    this.is_active = is_active;
}
public String getCreated_by() {
    return created_by;
}
public void setCreated_by(String created_by) {
    this.created_by = created_by;
}
public Date getCreated_ts() {
    return created_ts;
}
public void setCreated_ts(Date created_ts) {
    this.created_ts = created_ts;
}
public String getModified_by() {
    return modified_by;
}
public void setModified_by(String modified_by) {
    this.modified_by = modified_by;
}
public Date getModified_ts() {
    return modified_ts;
}
public void setModified_ts(Date modified_ts) {
    this.modified_ts = modified_ts;
}
public String getApproved_by() {
    return approved_by;
}
public void setApproved_by(String approved_by) {
    this.approved_by = approved_by;
}
public Date getApproved_ts() {
    return approved_ts;
}
public void setApproved_ts(Date approved_ts) {
    this.approved_ts = approved_ts;
}
}

请帮我解决这个问题..提前谢谢

【问题讨论】:

    标签: java spring hibernate jpa annotations


    【解决方案1】:

    试试这个:确定表 EntPpertySub 中的外键是如何调用的

    @OneToMany(cascade=CascadeType.ALL)
    @JoinColumn(name="propertyid")
    private List<EntPropertySub> blockListPropSub = new ArrayList<EntPropertySub>();
    

    无法在主表上创建物理列,因为您具有 OneToMany 关系。 OneToMany 表示 Master 有很多 Sub Table 引用。

    让我们解释一下问题:

    如果您要在主表中有一列,您需要在一个单元格中添加一个引用列表。

    举例

    ------------------ | sub-fk | |1, 2, 3, 4| <-- and this is against the database normalization

    但这不是必须的:

    Hibernate 会自动为你选择所有引用的子列(intern hibernate joins to the columns)

    如果使用entitymanager选择主数据,子数据包含在List blockListPropSub属性中

    【讨论】:

    • 它可以工作,但它没有在主表中创建一个单独的列,为什么?但我需要的是一个物理列也需要在主表中创建来引用一个子表...请解释代码..谢谢哥们
    • 我已经更新了帖子。希望你能理解。
    • 你说得对,但是我们可以创建一个对子表的主表引用是可能的..所以最后我在这段代码中做到了“@OneToMany(cascade=CascadeType.ALL)”“@ JoinColumn(name="propertyidfk")" private List blockListPropSub = new ArrayList();它将在子表中创建列,但我在父实体中编写了此代码...请注意,我们需要提供唯一名称而不是子/父表的主键列名称。然后只有它在子表中创建一个单独的列,因为我们使用的是 OneToMany 关系...
    【解决方案2】:

    最后我得到了答案..

    我对主实体“EntPropertyMaster”

    进行了更改
    "@OneToMany(cascade=CascadeType.ALL)"
    "@JoinColumn(name="propertyidfk")"  
    private List<EntPropertySub> blockListPropSub = new ArrayList<EntPropertySub>();
    

    它将在子表中创建列,但我在父实体中编写了这段代码...

    请注意,我们需要为列创建提供唯一的名称,然后它只会在子表中创建一个列....而不是主键列名 子/父表..

    【讨论】:

      【解决方案3】:

      该错误清楚地表明您的架构关系中缺少映射。

      您需要将EntPropertyMaster 映射到EntPropertySub

      @OneToMany(cascade=CascadeType.ALL, mappedBy="entPropertyMaster")
      private List<EntPropertySub> blockListPropSub = newArrayList<EntPropertySub>();
      

      在关系实体中也提供EntPropertyMaster映射。即

      @ManyToOne
      @JoinColumn(name="entPropertyMasterId",referencedColumnName="id")
      private EntPropertyMaster entPropertyMaster;
      

      JPA 中的关系始终是单向的,除非您关联 父母与孩子在两个方向。级联删除 从父母到孩子的操作将需要一个关系 父母对孩子(不只是相反)。

      【讨论】:

      • 嗯.. 有了这个解决方案,他将提供双向映射
      • 感谢好友回复,还是报错...标记为 mappedBy 的关联不能定义像“@”JoinTable 或“@”JoinColumn 之类的数据库映射:com.vfraternity.process.entity.EntPropertyMaster.blockListPropSub ...我编写了 OneToMany(cascade=CascadeType.ALL,mappedBy="EntPropertyMaster") 之类的代码
      • @mimu1011 不,两个实体不相互依赖。只有单向交通。第二个实体引用只是映射其他实体
      • @VigneshR 你需要在 EntPropertySub 模型中添加映射实体
      • 这使得它在双向正确?...我无法理解..你能在代码中解释我需要进行哪些更改吗?
      【解决方案4】:

      错误原因是:

      无法在 org.hibernate.mapping.Table(property_master) 中找到具有逻辑名称的列:propertysubpk

      原因是您的referencedColumnName 属性错误。它应该是:

      JPA 2.1 11.1.25:引用的列的名称 通过这个外键列。什么时候 与实体关系映射一起使用 除下述情况外, 引用的列在目标表中 实体。与单向一起使用时 OneToMany 外键映射,引用的 列在表中 源实体。在 Join 内使用时- 表注解,引用的键列 在拥有的实体表中 实体或反向实体,如果连接是 反向连接定义。当用于一个 集合表映射,引用 列在包含的实体的表中 集合。

      解释一下:@JoinColumn 在关系的 many 端创建一个列(此处为 EntPropertySub),其给定名称引用了 PK父实体,除非指定了 referencedColumnName。在后一种情况下,“many”表中的 FK 引用了referencedColumnName 中给出的列。在您的情况下,您想引用EntPropertyMaster 的PK,因此referencedColumnName 是多余的。只需使用:

      @OneToMany(cascade=CascadeType.ALL)
      @JoinColumn(name="propertysubfkid")
      private List<EntPropertySub> blockListPropSub = newArrayList<EntPropertySub>();
      

      【讨论】:

      • 它可以工作,但它没有在主表中创建一个单独的列,为什么?但我需要的是一个物理列也需要在主表中创建来引用一个子表...请解释代码..谢谢哥们
      • 为什么要在主表中创建列? 1-many 关系的工作方式(1 是主表,许多是子表)是在子表中放置一个 FK 列,引用主表的 PK。
      • 不在主表中,但需要在子表中创建,然后只能识别哪些数据引用到主表...这就是为什么..请检查我的答案我更新了它...
      【解决方案5】:

      当您在@OneToMany 关系上使用@JoinColumn 时,name 属性将指向相关表列,即EntPropertySub 实体,referencedColumnName 应指向其中的实体列存在@OneToMany 注释,即EntPropertyMaster

      所以基本上你有另一种方式,我认为它应该是:

      @OneToMany(cascade=CascadeType.ALL)
      @JoinColumn(name="propertysubpk", referencedColumnName="propertysubfkid")
      private List<EntPropertySub> blockListPropSub = newArrayList<EntPropertySub>();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-27
        • 2018-07-10
        • 2013-06-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多