No qualifying bean of type 'org.springframework.transaction.PlatformTransactionManager' available: expected single matching bean but found 2@Transactional@Transactional(transactionManager = "mmTransactionManager")No qualifying bean of type 'org.springframework.transaction.PlatformTransactionManager' available: expected single matching bean but found 2@Transactional@Transactional(transactionManager = "mmTransactionManager")<!– JPA –> <jpa:repositories base-package="pakageOfDAO1" entity-manager-factory-ref="mmEntityManager" transaction-manager-ref="mmTransactionManager"> </jpa:repositories> <jpa:repositories base-package="pakageOFDAO" entity-manager-factory-ref="mmEtcEntityManager" transaction-manager-ref="mmEtcTransactionManager" > </jpa:repositories> <!– Datasource ETC. –> <bean id="secondDatasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value=""/> <property name="url" value=""/> <property name="username" value=""/> <property name="password" value=""/> </bean> <!– Datasource, that is currently hsqldb (in-memory database). –> <bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value=""/> <property name="url" value=""/> <property name="username" value=""/> <property name="password" value=""/> </bean> <bean id="hibernateJpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/> <!– EntityEtcManagerFactory –>zxczx <bean id="mmEtcEntityManager" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" p:packagesToScan="pakage3" p:dataSource-ref="secondDatasource" p:persistenceUnitName="name2" > <property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter"/> <property name="jpaProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MariaDBDialect</prop> <prop key="hibernate.show-sql">true</prop> <prop key="hibernate.jdbc.batch_size">10</prop> </props> </property> </bean> <!– Transactions –> <bean id="mmEtcTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="mmEtcEntityManager"/> </bean> <!– EntityManagerFactory –> <bean id="mmEntityManager" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" p:packagesToScan="pakage1, pakage2" p:dataSource-ref="datasource" p:persistenceUnitName="name2" > <property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter"/> <property name="jpaProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop> <prop key="hibernate.show-sql">true</prop> <prop key="hibernate.jdbc.batch_size">10</prop> </props> </property> </bean> <!– Transactions –> <bean id="mmTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="mmEntityManager"/> </bean>
mmTransactionManager, em thử tìm kiếm xem có không và đặt 2 tên khác nhau nhé.
@Data public class DataSourceProperties { private final String driverClassName; private final String jdbcUrl; private final String username; private final String password; } @ConfigurationProperties(prefix = "hibernate") public class HibernateProperties extends Properties { private static final long serialVersionUID = -817908147155147987L; }
import javax.sql.DataSource; @Configuration @EnableConfigurationProperties(HibernateProperties.class) @ImportAutoConfiguration(RepositoryPropertiesConfig.class) public class EzyJpaConfig { @Autowired private ApplicationContext appContext; public static final String EXAMPLE1 = "example1"; public static final String EXAMPLE2 = "example2"; @Bean public EzyDataSourceFactory repositoryDataSourceFactory(RepositoryProperties properties) { return new EzyDataSourceFactory( properties.getDataSources(), appContext.getEnvironment(), "spring.datasource.hikari" ); } @Bean public EzyJpaRepositoryFactory repositoryJpaRepositoryFactory( EzyJpaTransactionManagerFactory repositoryJpaTransactionManagerFactory ) { return new EzyJpaRepositoryFactory(repositoryJpaTransactionManagerFactory); } @Bean public EzyEntityManagerFactoryFactory repositoryEntityManagerFactoryFactory( EzyDataSourceFactory repositoryDataSourceFactory, HibernateProperties hibernateProperties ) { return new EzyEntityManagerFactoryFactory( repositoryDataSourceFactory, hibernateProperties, "com.example.ezy.web.entity" ); } @Bean public EzyJpaTransactionManagerFactory repositoryJpaTransactionManagerFactory( EzyEntityManagerFactoryFactory repositoryEntityManagerFactoryFactory ) { return new EzyJpaTransactionManagerFactory(repositoryEntityManagerFactoryFactory); } // ==================== example1 ========== @Bean public DataSource example1DataSource(EzyDataSourceFactory repositoryDataSourceFactory) { return repositoryDataSourceFactory.createDataSource(EXAMPLE1); } @Bean public EntityManagerFactory example1EntityManagerFactory( DataSource example1DataSource, EzyEntityManagerFactoryFactory repositoryEntityManagerFactoryFactory ) { return repositoryEntityManagerFactoryFactory.createEntityManagerFactory( EXAMPLE1, example1DataSource ); } @Bean public JpaTransactionManager example1TransactionManager( EntityManagerFactory example1EntityManagerFactory, EzyJpaTransactionManagerFactory repositoryEntityManagerFactoryFactory ) { return repositoryEntityManagerFactoryFactory.createJpaTransactionManager( EXAMPLE1, example1EntityManagerFactory ); } // ==================== example2 ========== @Bean public DataSource example2DataSource(EzyDataSourceFactory repositoryDataSourceFactory) { return repositoryDataSourceFactory.createDataSource(EXAMPLE2); } @Bean public EntityManagerFactory example2EntityManagerFactory( DataSource example2DataSource, EzyEntityManagerFactoryFactory repositoryEntityManagerFactoryFactory ) { return repositoryEntityManagerFactoryFactory.createEntityManagerFactory( EXAMPLE2, example2DataSource ); } @Bean public JpaTransactionManager example2TransactionManager( EntityManagerFactory example2EntityManagerFactory, EzyJpaTransactionManagerFactory repositoryEntityManagerFactoryFactory ) { return repositoryEntityManagerFactoryFactory.createJpaTransactionManager( EXAMPLE2, example2EntityManagerFactory ); } // ================= config =========== @Getter @ConstructorBinding @AllArgsConstructor @ConfigurationProperties(prefix = "jpa") public static class RepositoryProperties { private final Map dataSources; } @Configuration @EnableConfigurationProperties(RepositoryProperties.class) @ConditionalOnMissingBean(RepositoryProperties.class) public static class RepositoryPropertiesConfig { } }
import javax.sql.DataSource; public final class JpaConfigurations { private JpaConfigurations() { } public static D createDataSource( DataSourceProperties properties, Class dataSourceClass ) { return DataSourceBuilder .create() .driverClassName(properties.getDriverClassName()) .url(properties.getJdbcUrl()) .username(properties.getUsername()) .password(properties.getPassword()) .type(dataSourceClass) .build(); } public static EntityManagerFactory createEntityManagerFactory( DataSource dataSource, HibernateProperties hibernateProperties, String packageToScan ) { final LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); factory.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); factory.setPackagesToScan(packageToScan); factory.setDataSource(dataSource); factory.setJpaProperties(hibernateProperties); factory.afterPropertiesSet(); return factory.getObject(); } public static JpaTransactionManager createJpaTransactionManager( EntityManagerFactory entityManagerFactory ) { return new JpaTransactionManager(entityManagerFactory); } }
import javax.sql.DataSource; @AllArgsConstructor public class EzyDataSourceFactory { private final Map dataSourcePropertiesByChainId; private final Environment environment; private final String hikariDataSourcePropertyPrefix; public DataSource createDataSource(String datasourceId) { final HikariDataSource dataSource = JpaConfigurations.createDataSource( dataSourcePropertiesByChainId.get(datasourceId), HikariDataSource.class ); final Binder binder = Binder.get(environment); binder.bind(hikariDataSourcePropertyPrefix, Bindable.ofInstance(dataSource)); return dataSource; } }
import javax.sql.DataSource; @AllArgsConstructor public class EzyEntityManagerFactoryFactory { private final EzyDataSourceFactory exampleDataSourceFactory; private final HibernateProperties hibernateProperties; private final String packageToScan; public EntityManagerFactory createEntityManagerFactory(String datasourceId) { return createEntityManagerFactory(datasourceId, null); } public EntityManagerFactory createEntityManagerFactory( String datasourceId, DataSource dataSource ) { return JpaConfigurations.createEntityManagerFactory( dataSource != null ? dataSource : exampleDataSourceFactory.createDataSource(datasourceId), hibernateProperties, packageToScan ); } }
@AllArgsConstructor public class EzyJpaRepositoryFactory { private final EzyJpaTransactionManagerFactory ezyJpaTransactionManagerFactory; public <T, I, R extends JpaRepository> R createJpaRepository( String datasourceId, Class jpaRepositoryClass, JpaTransactionManager jpaTransactionManager ) { final JpaTransactionManager actualJpaTransactionManager = jpaTransactionManager == null ? jpaTransactionManager : ezyJpaTransactionManagerFactory.createJpaTransactionManager(datasourceId); final EntityManagerFactory entityManagerFactory = actualJpaTransactionManager.getEntityManagerFactory(); assert entityManagerFactory != null; final EntityManager entityManager = SharedEntityManagerCreator.createSharedEntityManager(entityManagerFactory); final JpaRepositoryFactory jpaRepositoryFactory = new JpaRepositoryFactory(entityManager); final TransactionInterceptor transactionInterceptor = new TransactionInterceptor( (TransactionManager) actualJpaTransactionManager, new AnnotationTransactionAttributeSource() ); jpaRepositoryFactory.addRepositoryProxyPostProcessor((factory, repositoryInformation) -> factory.addAdvice(transactionInterceptor) ); return jpaRepositoryFactory.getRepository(jpaRepositoryClass); } public <T, I, R extends JpaRepository> R createJpaRepositoryWithAspects( String datasourceId, Class jpaRepositoryClass, JpaTransactionManager jpaTransactionManager, Object... aspects ) { final R nakedJpaRepository = createJpaRepository(datasourceId, jpaRepositoryClass, jpaTransactionManager); final AspectJProxyFactory proxyFactory = new AspectJProxyFactory(nakedJpaRepository); for (Object aspect : aspects) { proxyFactory.addAspect(aspect); } return proxyFactory.getProxy(); } }
@AllArgsConstructor public class EzyJpaTransactionManagerFactory { private final EzyEntityManagerFactoryFactory ezyEntryManagerFactoryFactory; public JpaTransactionManager createJpaTransactionManager(String datasourceId) { return createJpaTransactionManager(datasourceId, null); } public JpaTransactionManager createJpaTransactionManager( String datasourceId, EntityManagerFactory entityManagerFactory ) { return JpaConfigurations.createJpaTransactionManager( entityManagerFactory != null ? entityManagerFactory : ezyEntryManagerFactoryFactory.createEntityManagerFactory(datasourceId) ); } }