Java,Spring:创建一个单独的数据源bean将引发NonUnique错误 [英] Java, Spring : Create a separate datasource bean throws NonUnique error

查看:113
本文介绍了Java,Spring:创建一个单独的数据源bean将引发NonUnique错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究一个Spring-MVC应用程序,目前我们只有一个数据源。对于我们的要求,大多数交易要么是短暂的,我们确实有很少需要很长时间处理的应用程序。为避免系统因这些请求而被阻塞,我们计划创建一个单独的数据源。除此之外,这些方法的优先级较低,因为用户知道这些方法需要较长的时间。为此,我只需调用 Thread.currentThread()。setPriority(Thread.MIN_PRIORITY); 。这足够吗?主要的一点是,这些方法不应该在CPU,磁盘,I / O等上占用更多时间。

像其他spring-mvc应用程序一样,我们有3层,控制器,服务,DAO。一些服务层方法将在这些数据源之间共享。例如: long_method_service_layer() - > dependent_method_service_layer()。还有 short_method_service_layer() - > dependent_method_service_layer(); 所以现在当第二个数据源调用(),它是否也具有低优先级?



目前,我们的服务层是这样配置的:

  @Service 
@Transactional
public class DownloadTokenServiceImpl implements DownloadTokenService {

private final DownloadTokenDAO downloadTokenDAO;

@Autowired
public DownloadTokenServiceImpl(DownloadTokenDAO downloadTokenDAO){
this.downloadTokenDAO = downloadTokenDAO;
}

@Override
public void method_name(){}
}

来自第二个数据源的方法也将在这个类中。我打算用 @Transactional(2nd_source)分别注释这些方法。它是否正确?



最后,从我尝试的错误日志截至目前:

  
org.springframework.beans.factory.NoUniqueBeanDefinitionException:通过没有造成型的排位豆[org.hibernate.SessionFactory实例]被定义:预期单一匹配豆但发现2:hibernate4AnnotatedSessionFactory_extended,hibernate4AnnotatedSessionFactory
。在有机springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1133)
在org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1021)
。在组织。 springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:814)
在org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741)
。在组织。 s

root-context.xml:

第一个data_source (主要):

 < beans:bean id =dataSourceclass =com.zaxxer.hikari.HikariDataSourcedestroy -method = 关闭 > 
< beans:property name =dataSourceClassNamevalue =org.postgresql.ds.PGSimpleDataSource/>
< beans:property name =maximumPoolSizevalue =50/>
< beans:property name =maxLifetimevalue =200000/>
< beans:property name =idleTimeoutvalue =25000/>
< beans:property name =leakDetectionThresholdvalue =200000/>
< beans:property name =connectionTimeoutvalue =200000/>
< beans:property name =dataSourceProperties>
< beans:道具>
< beans:prop key =url> jdbc:postgresql:// localhost:5432 / DB_NAME< / beans:prop>
< beans:prop key =user>用户名< / beans:prop>
< beans:prop key =password>密码< / beans:prop>
< / beans:道具>
< / beans:property>
< / beans:bean>

<! - Hibernate 4 SessionFactory Bean定义 - >
< beans:bean id =hibernate4AnnotatedSessionFactory
class =org.springframework.orm.hibernate4.LocalSessionFactoryBean>
< beans:property name =dataSourceref =dataSource/>
< beans:property name =packagesToScanvalue =com.our_app.spring.model/>
< beans:property name =hibernateProperties>
< beans:道具>
< beans:prop key =hibernate.dialect> org.hibernate.dialect.PostgreSQL9Dialect< / beans:prop>
< beans:prop key =hibernate.jdbc.batch_size> 50< / beans:prop>
< beans:prop key =hibernate.hbm2ddl.auto> update< / beans:prop>
< beans:prop key =cache.use_second_level_cache> true< / beans:prop>
< beans:prop key =cache.use_query_cache> true< / beans:prop>
< beans:prop key =hibernate.order_updates> true< / beans:prop>
< beans:prop key =show_sql> false< / beans:prop>
< beans:prop key =connection.release_mode> after_statement< / beans:prop>
< / beans:道具>
< / beans:property>
< / beans:bean>


< tx:注解驱动的事务管理器=transactionManager/>

< beans:bean id =transactionManagerclass =org.springframework.orm.hibernate4.HibernateTransactionManager>
< beans:property name =sessionFactoryref =hibernate4AnnotatedSessionFactory/>
< / beans:bean>

第二个数据源(需要长时间运行的交易,一旦它工作,需要调整hikari值): p>

 < beans:bean id =extended_transactions_data_sourceclass =com.zaxxer.hikari.HikariDataSourcedestroy-method =close > 
< beans:property name =dataSourceClassNamevalue =org.postgresql.ds.PGSimpleDataSource/>
< beans:property name =maximumPoolSizevalue =50/>
< beans:property name =maxLifetimevalue =200000/>
< beans:property name =idleTimeoutvalue =25000/>
< beans:property name =leakDetectionThresholdvalue =200000/>
< beans:property name =connectionTimeoutvalue =200000/>
< beans:property name =dataSourceProperties>
< beans:道具>
< beans:prop key =url> jdbc:postgresql:// localhost:5432 / Db_NAME< / beans:prop>
< beans:prop key =user> USERNAME< / beans:prop>
< beans:prop key =password> passwoRD< / beans:prop>
< / beans:道具>
< / beans:property>
< / beans:bean>


<! - Hibernate 4 SessionFactory Bean定义 - >
< beans:bean id =hibernate4AnnotatedSessionFactory_extended
class =org.springframework.orm.hibernate4.LocalSessionFactoryBean>
< beans:属性名称=dataSourceref =extended_transactions_data_source/>
< beans:property name =packagesToScanvalue =com.our_app.spring.model/>
< beans:property name =hibernateProperties>
< beans:道具>
< beans:prop key =hibernate.dialect> org.hibernate.dialect.PostgreSQL9Dialect< / beans:prop>
< beans:prop key =hibernate.jdbc.batch_size> 50< / beans:prop>
< beans:prop key =hibernate.hbm2ddl.auto> update< / beans:prop>
< beans:prop key =cache.use_second_level_cache> true< / beans:prop>
< beans:prop key =cache.use_query_cache> true< / beans:prop>
< beans:prop key =hibernate.order_updates> true< / beans:prop>
< beans:prop key =show_sql> false< / beans:prop>
< beans:prop key =connection.release_mode> after_statement< / beans:prop>
< / beans:道具>
< / beans:property>
< / beans:bean>

< tx:注解驱动的事务管理器=transactionManager_extended/>

< beans:bean id =transactionManager_extendedclass =org.springframework.orm.hibernate4.HibernateTransactionManager>
< beans:property name =sessionFactoryref =hibernate4AnnotatedSessionFactory_extended/>
< / beans:bean>


解决方案

我不认为这是这篇文章,但它有一些很强的相似之处。看看那里接受的答案,并注意,在DAO中,他们自动连接两个会话工厂。作者还使用Qualifier注释来保持独立。在您的DAO中,您可能需要执行以下操作:

  @Autowired 
@Qualifier(value =hibernate4AnnotatedSessionFactory )
private SessionFactory hibernate4AnnotatedSessionFactory;

@Autowired
@Qualifier(值= hibernate4AnnotatedSessionFactory_extended)
私人的SessionFactory hibernate4AnnotatedSessionFactory_extended;

I think 在这种情况下,您不必限定事务注释,因为你的DAO实现将不得不显式使用一个会话工厂或其他。


I am working on a Spring-MVC application in which as of now we had a single data source. For our requirements, where most of the transactions are either short lived, we do have applications which rarely require very long time to process. To avoid the system being choked up because of those requests, we are planning to create a separate data source.

Other than that, those methods will have a lower priority, as user knows these will take a longer time. For that, I am simply calling Thread.currentThread().setPriority(Thread.MIN_PRIORITY); . Is this sufficient? The main point is, these methods should not consume more time on CPU, disk, I/O, etc.

Like other spring-mvc applications, we have 3 layers, controller, service, DAO. Some of the service layer methods will be shared amongst these data-sources. Example : long_method_service_layer()-->dependent_method_service_layer(). Also short_method_service_layer()-->dependent_method_service_layer();

So now when the 2nd datasource calls the dependent_method(), will it also have a low priority?

Currently, our service layer is configured this way :

@Service
@Transactional
public class DownloadTokenServiceImpl implements DownloadTokenService{

    private final DownloadTokenDAO downloadTokenDAO;

    @Autowired
    public DownloadTokenServiceImpl(DownloadTokenDAO downloadTokenDAO){
        this.downloadTokenDAO = downloadTokenDAO;
    }

@Override
public void method_name(){}
}

The methods from 2nd datasource will also be inside this class. I am planning to annotate those methods separately with @Transactional("2nd_source"). Is this correct?

Finally, Error log from my attempt as of now :

Caused by: 
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.hibernate.SessionFactory] is defined: expected single matching bean but found 2: hibernate4AnnotatedSessionFactory_extended,hibernate4AnnotatedSessionFactory
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1133)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1021)
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:814)
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741)
    at org.s

root-context.xml :

1st data_source (Primary) :

<beans:bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource"  destroy-method="close">
        <beans:property name="dataSourceClassName" value="org.postgresql.ds.PGSimpleDataSource"/>
       <beans:property name="maximumPoolSize" value="50" />
        <beans:property name="maxLifetime" value="200000" />
        <beans:property name="idleTimeout" value="25000" />
        <beans:property name="leakDetectionThreshold" value="200000"/>
        <beans:property name="connectionTimeout" value="200000"/>
        <beans:property name="dataSourceProperties">
            <beans:props>
                <beans:prop key="url">jdbc:postgresql://localhost:5432/DB_NAME</beans:prop>
                <beans:prop key="user">username</beans:prop>
                <beans:prop key="password">password</beans:prop>
            </beans:props>
        </beans:property>
    </beans:bean>

    <!-- Hibernate 4 SessionFactory Bean definition -->
    <beans:bean id="hibernate4AnnotatedSessionFactory"
                class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <beans:property name="dataSource" ref="dataSource"/>
        <beans:property name="packagesToScan" value="com.our_app.spring.model"/>
        <beans:property name="hibernateProperties">
            <beans:props>
                <beans:prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQL9Dialect</beans:prop>
                <beans:prop key="hibernate.show_sql">false</beans:prop>
                <beans:prop key="hibernate.jdbc.batch_size">50</beans:prop>
                <beans:prop key="hibernate.hbm2ddl.auto">update</beans:prop>
                <beans:prop key="cache.use_second_level_cache">true</beans:prop>
                <beans:prop key="cache.use_query_cache">true</beans:prop>
                <beans:prop key="hibernate.order_updates">true</beans:prop>
                <beans:prop key="show_sql">false</beans:prop>
                <beans:prop key="connection.release_mode">after_statement</beans:prop>
            </beans:props>
        </beans:property>
    </beans:bean>


    <tx:annotation-driven transaction-manager="transactionManager"/>

    <beans:bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <beans:property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory"/>
    </beans:bean>

2nd datasource(required for long running transactions, hikari values to be adjusted once its working) :

 <beans:bean id="extended_transactions_data_source" class="com.zaxxer.hikari.HikariDataSource"  destroy-method="close">
        <beans:property name="dataSourceClassName" value="org.postgresql.ds.PGSimpleDataSource"/>
        <beans:property name="maximumPoolSize" value="50" />
        <beans:property name="maxLifetime" value="200000" />
        <beans:property name="idleTimeout" value="25000" />
        <beans:property name="leakDetectionThreshold" value="200000"/>
        <beans:property name="connectionTimeout" value="200000"/>
        <beans:property name="dataSourceProperties">
            <beans:props>
                <beans:prop key="url">jdbc:postgresql://localhost:5432/Db_NAME</beans:prop>
                <beans:prop key="user">USERNAME</beans:prop>
                <beans:prop key="password">passwoRD</beans:prop>
            </beans:props>
        </beans:property>
    </beans:bean>


    <!-- Hibernate 4 SessionFactory Bean definition -->
    <beans:bean id="hibernate4AnnotatedSessionFactory_extended"
                class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <beans:property name="dataSource" ref="extended_transactions_data_source"/>
        <beans:property name="packagesToScan" value="com.our_app.spring.model"/>
        <beans:property name="hibernateProperties">
            <beans:props>
                <beans:prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQL9Dialect</beans:prop>
                <beans:prop key="hibernate.show_sql">false</beans:prop>
                <beans:prop key="hibernate.jdbc.batch_size">50</beans:prop>
                <beans:prop key="hibernate.hbm2ddl.auto">update</beans:prop>
                <beans:prop key="cache.use_second_level_cache">true</beans:prop>
                <beans:prop key="cache.use_query_cache">true</beans:prop>
                <beans:prop key="hibernate.order_updates">true</beans:prop>
                <beans:prop key="show_sql">false</beans:prop>
                <beans:prop key="connection.release_mode">after_statement</beans:prop>
            </beans:props>
        </beans:property>
    </beans:bean>

       <tx:annotation-driven transaction-manager="transactionManager_extended"/>

    <beans:bean id="transactionManager_extended" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <beans:property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory_extended"/>
    </beans:bean>

解决方案

I don't think this is an exact duplicate of this post, but it's got some strong similarities. Take a look at the accepted answer there and note that, in the DAO, they're autowiring both session factories. The author is also using the Qualifier annotation to keep separate. In your DAO, you may want to do something like:

  @Autowired
  @Qualifier(value="hibernate4AnnotatedSessionFactory")
  private SessionFactory hibernate4AnnotatedSessionFactory;

  @Autowired
  @Qualifier(value="hibernate4AnnotatedSessionFactory_extended")
  private SessionFactory hibernate4AnnotatedSessionFactory_extended;

I think in this case, you wouldn't have to qualify the Transactional annotations, since your DAO implementation will have to explicitly use one session factory or the other.

这篇关于Java,Spring:创建一个单独的数据源bean将引发NonUnique错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆