当前位置: 首页 > 面试题库 >

JPA / Hibernate嵌入式ID

柳飞飙
2023-03-14
问题内容

我想做这样的事情:

  • 对象ReportingFile可以是LogRequest或LogReport文件。(两者结构相同)
  • 一个对象Reporting,其中包含一个logRequest,其中包含带日期的logReport列表。

我试图设置一个EmbededId,这将是logRequest的属性。这就是我遇到的问题。我没有来管理嵌入式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

问题答案:

好的,我们等着瞧

您有一个@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<ReportingFile> 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<ReportingFile> reports;

还有更多:我不知道您的目标数据库是否支持Clob作为主键。因此请记住这一点。

根据您的回复添加到原始答案

第一种情况( 不带 @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

第一种情况( 带有 @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类定义为静态类。



 类似资料:
  • 问题内容: 我在映射类的嵌入式属性时遇到麻烦。我创建了一些类,这些类与我试图说明的类相似。基本上,我有一个使用继承的@Embeddable类层次结构。顶级类“零件号”只有一个属性,扩展类没有为“零件号”类添加属性,它们仅添加了一些验证/逻辑。 这是我的意思: 部分 零件号 福特PARTNUMBER 高贵的零件编号 当然这是行不通的,因为Hibernate忽略了继承层次结构,并且不喜欢PartNum

  • 问题内容: JPA实体类是否可以包含两个嵌入式()字段?一个例子是: 在这种情况下,a 可以包含两个实例-家庭和工作。我在Hibernate的实现中使用JPA。当我使用Hibernate Tools生成架构时,它仅嵌入一个。我想要的是两个嵌入式实例,每个实例的列名都经过区分或在前面加上一些前缀(例如home和work)。我知道,但是这要求每个属性都应单独覆盖。如果嵌入的对象()变大,那么这会变得很

  • 我想向实体类添加嵌入关系。 在我的数据库中,我有表蛋白质: 和表基准: 在基准测试中,字段目标是蛋白质表的外键 我已经从蛋白质表中找到了一个名为SupProtein的实体,它运行良好。 现在,我想向基准类添加一个嵌入关系。 这是我的基准课程: 在我的实体课程中,我添加了: 但当我尝试构建时,会出现以下错误: 我没有创建任何ORM. xml文件,在任何地方都找不到。我需要一个orm.xml文件来创建

  • 我正在运行Hibernate 4.2.6。Final/JPA2,并尝试创建一个由@embedded对象组成的@ElementCollection列表,这些对象本身包含一个字符串的@ElementCollection列表。 但是,当尝试实例化EntityManager时,hibernate会抛出一个ContoptModificationException,我一点也不明白。 如果我注释掉我的

  • 问题内容: 我正在运行Hibernate 4.2.6.Final / JPA2,并尝试具有@Embeddable对象的@ElementCollection列表,这些对象本身包含String的@ElementCollection列表。 但是,hibernate在尝试实例化EntityManager时抛出ConcurrentModificationException,我根本不了解。 如果我注释掉in

  • 问题内容: 我想在 独立应用程序* 中将 hibernate 与 嵌入式derby 一起使用,并且我有一些问题: * 我需要什么jar? 必要的hibernate配置是什么? 还有其他必要的配置吗? 查询/条件是否有任何问题/限制? 如果您还可以建议我一些适合这种方法的好教程,那将是可取的,谢谢。 问题答案: 我将Apache Derby与Hibernate一起用于测试项目的一个模型类(它们的 e