我想做那样的事情:
我尝试设置一个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<ReportingFile> 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.<init>(PersistenceExceptionTranslationInterceptor.java:78)
at org.springframework.dao.annotation.PersistenceExceptionTranslationAdvisor.<init>(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
答案 0 :(得分:12)
好吧,让我们看看
你有API所说的@AssociationOverride注释:
此注释用覆盖实体关系的属性或字段的多对一或一对一映射。
和
可以将应用于扩展映射超类的实体,以覆盖由映射的超类定义的多对一或一对一映射
我的问题中既没有看到@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<ReportingFile> reports;
其外键仅包含一个属性,而您的Compound主键包含两个属性。 两者必须匹配。它解释了为什么你看到这个好消息
引用来自报告的报告的外键具有错误的列数。应该是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<ReportingFile> 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<ReportingFile> 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<Clob> xmlContents;
@Transient
public List<ReportingFile> getReports() {
List<ReportingFile> reports = new ArrayList<ReportingFile>();
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类定义为静态。