JPA / Hibernate Embedded id
我想做那样的事情:
- ReportingFile对象,可以是LogRequest或LogReport文件。 (两者都有相同的结构)
- 一个对象报告包含一个logRequest,一个带有日期的logReport列表。
我尝试设置一个EmbededId,它将是logRequest的一个属性。 这就是我遇到的问题。 我没有到达mannage嵌入式id。 ( http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#entity-mapping-identifier )
如果你有一个关于我应该怎么做的线索:)
一个例子(不工作)将是:
@Entity @AssociationOverride( name="logRequest.fileName", joinColumns = { @JoinColumn(name="log_request_file_name") } ) public class Reporting { @EmbeddedId private ReportingFile logRequest; @CollectionOfElements(fetch = FetchType.EAGER) @JoinTable(name = "t_reports", schema="", joinColumns = {@JoinColumn(name = "log_report")}) @Fetch(FetchMode.SELECT) private List reports; @Column(name="generated_date",nullable=true) private Date generatedDate; [...] } @Embeddable public class ReportingFile { @Column(name="file_name",length=255) private String fileName; @Column(name="xml_content") private Clob xmlContent; [...] }
在此示例中,我有以下错误:
15.03.2010 16:37:59 [ERROR] org.springframework.web.context.ContextLoader Context initialization failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor#0' defined in class path resource [config/persistenceContext.xml]: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [config/persistenceContext.xml]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: test] Unable to configure EntityManagerFactory at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:480) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409) at java.security.AccessController.doPrivileged(Native Method) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:221) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164) at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:881) at org.springframework.context.support.AbstractApplicationContext.registerBeanPostProcessors(AbstractApplicationContext.java:597) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:366) at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:255) at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:199) at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:45) at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3843) at org.apache.catalina.core.StandardContext.start(StandardContext.java:4350) at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045) at org.apache.catalina.core.StandardHost.start(StandardHost.java:719) at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045) at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443) at org.apache.catalina.core.StandardService.start(StandardService.java:516) at org.apache.catalina.core.StandardServer.start(StandardServer.java:710) at org.apache.catalina.startup.Catalina.start(Catalina.java:578) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288) at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413) Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [config/persistenceContext.xml]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: test] Unable to configure EntityManagerFactory at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1337) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:473) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409) at java.security.AccessController.doPrivileged(Native Method) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:221) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164) at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:308) at org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors(BeanFactoryUtils.java:270) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.detectPersistenceExceptionTranslators(PersistenceExceptionTranslationInterceptor.java:122) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.(PersistenceExceptionTranslationInterceptor.java:78) at org.springframework.dao.annotation.PersistenceExceptionTranslationAdvisor.(PersistenceExceptionTranslationAdvisor.java:70) at org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor.setBeanFactory(PersistenceExceptionTranslationPostProcessor.java:97) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1325) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:473) ... 29 more Caused by: javax.persistence.PersistenceException: [PersistenceUnit: test] Unable to configure EntityManagerFactory at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:265) at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:125) at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:83) at org.springframework.orm.jpa.LocalEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalEntityManagerFactoryBean.java:91) at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:291) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1368) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1334) ... 46 more Caused by: org.hibernate.AnnotationException: A Foreign key refering Reporting from Reporting has the wrong number of column. should be 2 at org.hibernate.cfg.annotations.TableBinder.bindFk(TableBinder.java:272) at org.hibernate.cfg.annotations.CollectionBinder.bindCollectionSecondPass(CollectionBinder.java:1319) at org.hibernate.cfg.annotations.CollectionBinder.bindManyToManySecondPass(CollectionBinder.java:1158) at org.hibernate.cfg.annotations.CollectionBinder.bindStarToManySecondPass(CollectionBinder.java:600) at org.hibernate.cfg.annotations.CollectionBinder$1.secondPass(CollectionBinder.java:541) at org.hibernate.cfg.CollectionSecondPass.doSecondPass(CollectionSecondPass.java:43) at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1140) at org.hibernate.cfg.AnnotationConfiguration.secondPassCompile(AnnotationConfiguration.java:319) at org.hibernate.cfg.Configuration.buildMappings(Configuration.java:1125) at org.hibernate.ejb.Ejb3Configuration.buildMappings(Ejb3Configuration.java:1226) at org.hibernate.ejb.EventListenerConfigurator.configure(EventListenerConfigurator.java:159) at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:854) at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:191) at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:253) ... 52 more
好的,我们等着瞧
你有一个@AssociationOverride注释,它的API说:
此批注用于覆盖实体关系的属性或字段的多对一或一对一映射。
和
它可以应用于扩展映射的超类的实体,以覆盖由映射的超类定义的多对一或一对一映射
在你的问题中,我既没有看过@ManyToOne也没看过@OnoToOne。 所以,你的问题有问题。
但是我在StackTrace中看到了以下日志
引用报告来自报告的外键具有错误的列数。 应该是2
你有一个由@EmbeddedId注释定义的复合主键 ,它有两个属性(fileName和xmlContent)
现在,让我们看看你的@CollectionOfElements
@CollectionOfElements(fetch=FetchType.EAGER) @JoinTable(name="t_reports", // Your mistake goes here joinColumns=@JoinColumn(name="log_report")) @Fetch(FetchMode.SELECT) private List reports;
它的外键只包含一个属性,而复合主键包含两个属性 。 两者都必须匹配 。 它解释了为什么你看到这个好消息
引用报告来自报告的外键具有错误的列数。 应该是2
您的正确映射应如下所示
@CollectionOfElements(fetch=FetchType.EAGER) @JoinTable(name="t_reports", joinColumns={ // The number of columns defined by our Compound primary key (2) // must match the number of columns defined by its Foreign key (2) @JoinColumn(name="file_name", referencedColumnName="file_name"), @JoinColumn(name="xml_content", referencedColumnName="xml_content")}) @Fetch(FetchMode.SELECT) private List reports;
还有更多:我不知道您的目标数据库是否支持Clob作为主键。 所以记住它。
根据您的回复添加到原始答案
1º第一种情况( 没有 @CollectionOfElements)
@Entity public class Reporting { // You said you just want a single fileName as primary key @Id @Column(name="file_name", nullable=false) private String fileName; // You said you still want to have the whole ReportingFile object @Embedded private ReportingFile reportingFile; @Embeddable public static class ReportingFile implements Serializable { // You must set up insertable=false, updatable=false @Column(name="file_name", insertable=false, updatable=false) private String fileName; @Column(name="xml_content") private Clob xmlContent; } }
请记住以下内容:Hibernate 不允许您定义两个共享同一列的属性 。 因此,我必须在fileName属性中定义insertable = false,updatable = false。
当我做以下事情时
Reporting reporting = new Reporting(); reporting.setFileName("home.pdf"); ReportingFile reportingFile = new ReportingFile(); // It will not persisted because of insertable=false, updatable=false reportingFile.setFileName("home.pdf"); reportingFile.setXmlContent(someClobObject); session.save(reporting); // It works
2º第一种情况( 使用 @CollectionOfElements)
@Entity public class Reporting { // You said you just want a single fileName as primary key @Id @Column(name="file_name", nullable=false) private String fileName; // You said you still want to have the whole ReportingFile object @Embedded private ReportingFile reportingFile; @CollectionOfElements(fetch=FetchType.EAGER) @JoinTable( name="t_reports", joinColumns=@JoinColumn(name="file_name", referencedColumnName="file_name", insertable=false, updatable=false)) private List reports; @Embeddable public static class ReportingFile implements Serializable { // You must set up insertable=false, updatable=false @Column(name="file_name", insertable=false, updatable=false) private String fileName; @Column(name="xml_content") private Clob xmlContent; } }
当我做以下事情时
Reporting reporting = new Reporting(); reporting.setFileName("home.pdf"); ReportingFile reportingFile = new ReportingFile(); // It will not persisted because of insertable=false, updatable=false reportingFile.setFileName("home.pdf"); reportingFile.setXmlContent(someClobObject); reporting.getReports().add(reportingFile); session.save(reporting); // It does not work
Hibernate会抱怨
集合映射中的重复列:报告列:file_name
因此,当您拥有共享外键的@CollectionOfElements时, 它将无法按预期工作 。 但你可以做一个解决方法
@Entity public class Reporting { // You said you just want a single fileName as primary key @Id @Column(name="file_name", nullable=false) private String fileName; // You said you still want to have the whole ReportingFile object @Embedded private ReportingFile reportingFile; // Your workaround goes here @CollectionOfElements(fetch=FetchType.EAGER) @JoinTable( name="t_reports", joinColumns=@JoinColumn(name="file_name", referencedColumnName="file_name")) private List xmlContents; @Transient public List getReports() { List reports = new ArrayList (); for(Clob xmlContent: getXmlContents()) reports.add(new ReportingFile(getFileName(), xmlContent)); return reports; } @Embeddable public static class ReportingFile implements Serializable { // required no-arg constructor public ReportingFile() {} public ReportingFile(String fileName, Clob xmlContent) { this.fileName = fileName; this.xmlContent = xmlContent; } // You must set up insertable=false, updatable=false @Column(name="file_name", insertable=false, updatable=false) private String fileName; @Column(name="xml_content") private Clob xmlContent; } }
请注意,在您拥有的类中使用时,您可以将@Embeddable类定义为静态。
- HQL加入查询以急切获取大量关系
- 在hibernate / jpa最佳实践问题中将分离的或新的实体与现有实体合并
- 创建名为’org.springframework.security.filterChains’Spring + Hibernate + UserDetailService的bean时出错
- JPA和Hibernate初始化非惰性集合错误
- 如何拦截Hibernate生成的SQL?
- Hibernate使用hibernate.jdbc.batch_versioned_data保存过时数据
- Hibernate 5中不推荐使用createCriteria方法
- 如何使用hibernate将多行插入数据库?
- Hibernate + Oracle IN子句限制,如何解决呢?