【问题标题】:How to use a specific database only for managed operations如何仅将特定数据库用于托管操作
【发布时间】:2013-11-18 07:27:26
【问题描述】:

我们使用 spring 和 jpa 2.0 我管理的 bean 调用了与客户端相同的方法。 我希望托管 bean 在从数据库上运行,客户端在主数据库上调用。

关于我们如何做到这一点的任何想法?

谢谢

Here is my xml file defining datasources :

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> <!-- connection pool datasource which supports also XA 2 phase commit -->
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>

    <property name="url" value="jdbc:mysql://localhost:3306/netoplay"/>
    <property name="username" value="root" />
    <property name="password" value="" />

    <property name="initialSize" value="10"/>
    <property name="maxActive" value="100"/> <!-- The maximum number of active connections that can be allocated from this pool at the same time, or negative for no limit. -->
    <property name="maxIdle" value="15"/> <!-- The maximum number of connections that can remain idle in the pool, without extra ones being released, or negative for no limit. -->
    <property name="minIdle" value="10"/> <!-- The minimum number of connections that can remain idle in the pool, without extra ones being created, or zero to create none. -->
    <property name="timeBetweenEvictionRunsMillis" value="10000"/> <!-- the idle evicter thread evicts idle connections -->
    <property name="minEvictableIdleTimeMillis" value="60000"/> <!-- time a connection may be idle until it can be evicted -->

    <property name="validationQuery" value="/* ping */ SELECT 1"/>
    <property name="testOnBorrow" value="true"/> <!-- test the connection using the ping validationQuery before it is given to the application -->
    <property name="testWhileIdle" value="true"/> <!-- in addition to testOnBorrow, test connections while they are sitting idle -->

    <!-- If you enable "removeAbandoned" then it is possible that a connection is reclaimed by the pool because it is considered to be abandoned. This mechanism is triggered when (getNumIdle() < 2) and (getNumActive() > getMaxActive() - 3) -->
    <property name="removeAbandoned" value="true"/> <!-- Flag to remove abandoned connections if they exceed the removeAbandonedTimout. If set to true a connection is considered abandoned and eligible for removal if it has been idle longer than the removeAbandonedTimeout. Setting this to true can recover db connections from poorly written applications which fail to close a connection. -->
    <property name="removeAbandonedTimeout" value="300"/> <!-- Timeout in seconds before an abandoned connection can be removed. 300 seconds (5 minutes) is the default -->

</bean>

<bean id="dataSourceSlaveDB" class="org.apache.commons.dbcp.BasicDataSource"> <!-- connection pool datasource which supports also XA 2 phase commit -->
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>

    <property name="url" value="jdbc:mysql://localhost:3306/netoplay"/>
    <property name="username" value="root" />
    <property name="password" value="" />

    <property name="initialSize" value="10"/>
    <property name="maxActive" value="100"/> <!-- The maximum number of active connections that can be allocated from this pool at the same time, or negative for no limit. -->
    <property name="maxIdle" value="15"/> <!-- The maximum number of connections that can remain idle in the pool, without extra ones being released, or negative for no limit. -->
    <property name="minIdle" value="10"/> <!-- The minimum number of connections that can remain idle in the pool, without extra ones being created, or zero to create none. -->
    <property name="timeBetweenEvictionRunsMillis" value="10000"/> <!-- the idle evicter thread evicts idle connections -->
    <property name="minEvictableIdleTimeMillis" value="60000"/> <!-- time a connection may be idle until it can be evicted -->

    <property name="validationQuery" value="/* ping */ SELECT 1"/>
    <property name="testOnBorrow" value="true"/> <!-- test the connection using the ping validationQuery before it is given to the application -->
    <property name="testWhileIdle" value="true"/> <!-- in addition to testOnBorrow, test connections while they are sitting idle -->

    <!-- If you enable "removeAbandoned" then it is possible that a connection is reclaimed by the pool because it is considered to be abandoned. This mechanism is triggered when (getNumIdle() < 2) and (getNumActive() > getMaxActive() - 3) -->
    <property name="removeAbandoned" value="true"/> <!-- Flag to remove abandoned connections if they exceed the removeAbandonedTimout. If set to true a connection is considered abandoned and eligible for removal if it has been idle longer than the removeAbandonedTimeout. Setting this to true can recover db connections from poorly written applications which fail to close a connection. -->
    <property name="removeAbandonedTimeout" value="300"/> <!-- Timeout in seconds before an abandoned connection can be removed. 300 seconds (5 minutes) is the default -->

</bean>

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="punit"/>
    <property name="dataSource" ref="dataSource"/>
    <property name="jpaDialect">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
    </property>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="database" value="MYSQL"/>
            <!-- <property name="databasePlatform" value="${hibernate.dialect}"/> -->
            <property name="showSql" value="false"/>
            <property name="generateDdl" value="false"/>
            <!--  <property name="hibernate.connection.autocommit" value="false"/> -->
        </bean>
    </property>
    <property name="jpaPropertyMap">
        <map>
            <entry key="hibernate.connection.autocommit" value="false" />
        </map>
    </property>
</bean>

这是我的 persistence.xml 文件:

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0">    
<persistence-unit name="punit"> <!-- transaction-type="JTA" JTA is the defailt --> 
    <properties>
        <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>           
    </properties>
</persistence-unit>

【问题讨论】:

  • 嗯...很容易降低问题分数,有点难以说出原因或回答问题。
  • 你试过什么?您的 persistence.xml 定义在哪里?显然,JPA 需要一个持久性单元,您可以拥有一个用于主数据库和一个用于从数据库。很好,很好地批评人们投反对票,但您在问题上花费的时间最少。
  • 我可以在这里写我的 persistence.xml 你会看到定义了两个数据源,但我的问题是如何在不修改我的所有方法的情况下告诉使用哪个数据源,将数据源作为参数或添加一个 bean在我所有的课程中精确使用的数据源。
  • 但那些是数据源而不是 persistence.xml。在持久化单元中,您可以指定相应单元将使用的 jtaDataSource / nonJtaDataSource(取决于是否使用 JTA)(因此将它们设置为“dataSource”或“dataSourceSlaveDB”)。您没有为您的客户端或服务器提供关于他们如何获得 EMF 的代码

标签: java spring jpa mbeans


【解决方案1】:

背景:当您使用自动事务管理时,Spring 最终(通常在您进行第一次 DB 访问时)会创建一个会话。这时候就需要在两个数据库之间切换了。

因此,您需要做的是禁用自动事务管理并用手动管理替换它。查找调用客户端代码的位置和调用 mbean 的位置。用手动事务管理包装这些并创建适当的会话。

根据您的代码的工作方式,这可能需要大量工作。然后,诀窍是确定需要更多工作的一方。假设您有 500 个调用 mbean 的位置,但您可以为所有客户端调用安装一个 HTTP 过滤器,因为它使用 HTTP。

因此,您创建了一个过滤器,为客户端数据库创建会话并将其配置到您的 HTTP 堆栈中。对于 mbean,您使用 Spring 的自动事务管理,您可以将其配置为连接到从属数据库。

由于正常的事务管理在会话已经存在时不做任何事情,所有代码都将转到正确的数据库。

注意:在这种情况下,您不能使用自动缓存。如果你这样做了,来自两个数据库的对象将最终进入你的缓存,并且真正可怕的事情将开始发生。

【讨论】:

  • 非常感谢您提供这些详细信息
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-05
  • 2010-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-06
相关资源
最近更新 更多