hibernate异常:无法直接示例化托管bean

1tu0hz3e  于 2021-07-23  发布在  Java
关注(0)|答案(1)|浏览(380)

我有一个案例需要两个entitymanager示例,一个用于读/写,另一个用于审计跟踪。
我们通过执行以下操作创建了entity manager的两个示例:
//在app.java中,我们添加了以下注解:

@Configuration
@EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class })

然后创建了两个实体管理器,如下所示:1:

package com.vw.asa.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.persistence.PersistenceContext;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

@EnableTransactionManagement
@Configuration
@EnableJpaRepositories(basePackages = "com.vw.asa.repositories", entityManagerFactoryRef = "entityManager", transactionManagerRef = "transactionManager")
public class PrimaryDatasource {

    /**
     * Primary Datasource Configuration
     * @return
     */
    @Bean(name = "dataSource")      // 3
    @Primary
    @ConfigurationProperties(prefix = "primary.datasource.mysql")
    public DataSource mysqlDataSource() {
        return DataSourceBuilder.create().build();
    }

    @PersistenceContext(unitName = "primary")   // 4
    @Primary
    @Bean(name = "entityManagerFactory")
    public LocalContainerEntityManagerFactoryBean mySqlEntityManagerFactory(EntityManagerFactoryBuilder builder) {
        return builder.dataSource(mysqlDataSource())
                .persistenceUnit("primary")
                .properties(jpaProperties())
                .packages("com.vw.asa").build();
    }

    private Map<String, Object> jpaProperties() {
        Map<String, Object> props = new HashMap<>();
        props.put("hibernate.ejb.naming_strategy", new SpringPhysicalNamingStrategy());
        return props;
    }

}

2:

package com.vw.asa.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.persistence.PersistenceContext;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

@EnableTransactionManagement
@Configuration
@EnableJpaRepositories(basePackages = "com.vw.asa.repositories", entityManagerFactoryRef = "secondaryMySqlEntityManager", transactionManagerRef = "secondaryTransactionManager")
public class SecondaryDatasource {

    /**
     * Secondary Datasource Configuration
     * @return
     */
    @Bean
    @ConfigurationProperties(prefix = "secondary.datasource.mysql")
    public DataSource mysqlDataSource() {
        return DataSourceBuilder.create().build();
    }

    @PersistenceContext(unitName = "secondary")
    @Bean(name = "secondaryMySqlEntityManager")
    public LocalContainerEntityManagerFactoryBean mySqlEntityManagerFactory(EntityManagerFactoryBuilder builder) {
        return  builder.dataSource(mysqlDataSource()).properties(jpaProperties()).persistenceUnit("secondary").packages("au.com.myblog.domain").build();
    }

    @Bean(name = "secondaryTransactionManager")
    public PlatformTransactionManager transactionManager(EntityManagerFactoryBuilder builder) {
        JpaTransactionManager tm = new JpaTransactionManager();
        tm.setEntityManagerFactory(mySqlEntityManagerFactory(builder).getObject());
        tm.setDataSource(mysqlDataSource());
        return tm;
    }

    private Map<String, Object> jpaProperties() {
        Map<String, Object> props = new HashMap<>();
        // naming strategy to put underscores instead of camel case
        // as per auto JPA Configuration
        props.put("hibernate.ejb.naming_strategy", new SpringPhysicalNamingStrategy());
        props.put("hibernate.hbm2ddl.auto", "none");
        return props;
    }

}

但是,在运行应用程序时,会遇到以下异常:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [com/vw/asa/config/PrimaryDatasource.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: primary] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.InstantiationException: Could not instantiate managed bean directly : com.vw.asa.listeners.AttachmentListener
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1796)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:595)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:517)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:323)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:321)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
    at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:330)
    ... 121 more
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: primary] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.InstantiationException: Could not instantiate managed bean directly : com.vw.asa.listeners.AttachmentListener
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:403)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:378)
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1855)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1792)
    ... 128 more
Caused by: org.hibernate.InstantiationException: Could not instantiate managed bean directly : com.vw.asa.listeners.AttachmentListener
    at org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer.produceBeanInstance(FallbackBeanInstanceProducer.java:45)
    at org.hibernate.resource.beans.container.spi.FallbackContainedBean.<init>(FallbackContainedBean.java:23)
    at org.hibernate.resource.beans.internal.ManagedBeanRegistryImpl.getBean(ManagedBeanRegistryImpl.java:58)
    at org.hibernate.jpa.event.internal.CallbackBuilderLegacyImpl.resolveEntityCallbacks(CallbackBuilderLegacyImpl.java:200)
    at org.hibernate.jpa.event.internal.CallbackBuilderLegacyImpl.buildCallbacksForEntity(CallbackBuilderLegacyImpl.java:74)
    at org.hibernate.event.service.internal.EventListenerRegistryImpl.prepare(EventListenerRegistryImpl.java:146)
    at org.hibernate.boot.internal.MetadataImpl.initSessionFactory(MetadataImpl.java:376)
    at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:211)
    at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:468)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1237)
    at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:58)
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:391)
    ... 132 more
Caused by: java.lang.NoSuchMethodException: com.vw.asa.listeners.AttachmentListener.<init>()
[2021-02-21 08:43:48,090] Artifact vw-asa:war exploded: Error during artifact deployment. See server log for details.
    at java.lang.Class.getConstructor0(Class.java:3082)
    at java.lang.Class.getDeclaredConstructor(Class.java:2178)
    at org.hibernate.resource.beans.internal.FallbackBeanInstanceProducer.produceBeanInstance(FallbackBeanInstanceProducer.java:40)
    ... 144 more

我们的想法是,我们可以确定在给定的事务中使用哪个em。是什么原因造成的?如果我从中重命名它,它会抛出不同的错误 EntityManagerFactory

pftdvrlh

pftdvrlh1#

问题是entitylistener没有提供默认(无参数)构造函数,hibernate需要它来示例化侦听器。
如果您使用的是hibernate 5.3或更高版本,您可以通过如下方式将beancontainer设置到entitymanagerfactory中,让spring为这些bean提供休眠:

public LocalContainerEntityManagerFactoryBean mySqlEntityManagerFactory(EntityManagerFactoryBuilder builder, ConfigurableListableBeanFactory beanFactory) {
    LocalContainerEntityManagerFactoryBean emfb = builder.dataSource(mysqlDataSource())
            .persistenceUnit("primary")
            .properties(jpaProperties())
            .packages("com.vw.asa").build();
    emfb.getJpaPropertyMap().put(AvailableSettings.BEAN_CONTAINER, new SpringBeanContainer(beanFactory));
    return emfb;
}

相关问题