如何使用JPA和Hibernate

时间:2017-10-23 11:05:59

标签: java spring hibernate jpa annotations

我的项目基于spring boot,Thymeleaf,mysql,html和Jquery。我试图在维护中使用单向的@oneToMany关系,但它只产生错误,如

  

启动ApplicationContext时出错。要显示自动配置报告,请使用' debug'重新运行您的应用程序。启用。   2017-10-23 16:17:49.908 ERROR 18724 --- [main] o.s.boot.SpringApplication:应用程序启动失败

     

org.springframework.beans.factory.BeanCreationException:错误   创建名为&entityManagerFactory'的bean在类路径中定义   资源   [组织/ springframework的/引导/自动配置/ ORM / JPA / HibernateJpaAutoConfiguration.class]:   调用init方法失败;嵌套异常是   org.hibernate.AnnotationException:无法映射集合   com.vfraternity.process.entity.EntPropertyMaster.blockListPropSub at 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]引起:org.hibernate.AnnotationException:无法执行   地图集合   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个常用帧   引起:org.hibernate.cfg.RecoverableException:无法找到   具有逻辑名称的列:propertysubpk in   org.hibernate.mapping.Table(property_master)及其相关   在supertables和次要表   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个常见帧   省略:org.hibernate.MappingException:无法找到   具有逻辑名称的列:propertysubpk in   org.hibernate.mapping.Table(property_master)及其相关   在supertables和次要表   org.hibernate.cfg.Ejb3JoinColumn.checkReferencedColumnsType(Ejb3JoinColumn.java:826)   〜[hibernate-core-5.2.10.Final.jar:5.2.10.Final] ... 33个常见帧   省略

我尝试使用

实现单向
@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     package 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;
}
}

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

5 个答案:

答案 0 :(得分:1)

试试这个:确保表EntPopertySub中的外键如何调用

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

由于您具有OneToMany关系,因此无法在主表上创建物理列。 OneToMany意味着Master有许多Sub Table引用。

让我们解释一下问题:

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

例如

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

但这不是必要的:

Hibernat将自动为您选择所有引用的子列(实习生hibernat连接到列)

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

答案 1 :(得分:1)

错误原因是:

  

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

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

  

JPA 2.1 11.1.25:引用列的名称   通过这个外键列。什么时候   与实体关系映射一起使用   除了下面描述的情况,   引用列位于目标表中   实体即可。与单向一起使用时   OneToMany外键映射,引用   列在表中   来源实体。在加入内使用时 -   表注释,引用的键列   在拥有的实体表中   实体,如果连接是其中一部分,则为反向实体   逆连接定义。用于   集合表映射,引用   列位于包含实体的表中   集合。

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

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

答案 2 :(得分:0)

错误清楚地显示了架构关系中缺少的映射。

您需要在EntPropertyMaster中映射EntPropertySub

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

在关系实体中也提供EntPropertyMaster映射.i.e。

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

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

答案 3 :(得分:0)

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

所以基本上你有其他方式,它应该在我看来:

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

答案 4 :(得分:0)

Finnaly我得到了答案..

我在主实体“EntPropertyMaster”

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

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

  

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