我有一个案例需要两个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
1条答案
按热度按时间pftdvrlh1#
问题是entitylistener没有提供默认(无参数)构造函数,hibernate需要它来示例化侦听器。
如果您使用的是hibernate 5.3或更高版本,您可以通过如下方式将beancontainer设置到entitymanagerfactory中,让spring为这些bean提供休眠: