I have a project that currently uses 3 databases on the same database server. One of the databases has now been moved to another physical server and I'm trying to get hibernate to handle this but struggling to work out where to start - should I duplicate datasource, sessionfactory, hibernatetemplate, and transaction manager and then try to manage this in the code? I'm using Spring 3 and Hibernate 3.5. Is this a common thing to do? Any advice would be much appreciated.
If it helps my config currently looks like this:
<bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/DatabaseOne"/>
<property name="username" value="username"/>
<property name="password" value="password"/>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="datasource"/>
<property name="exposeTransactionAwareSessionFactory"><value>true</value></property>
<property name="annotatedClasses">
<list>
<value>domain.DatabaseOneObject</value>
<value>domain.DatabaseTwoObject</value>
<value>domain.DatabaseThreeObject</value>
</list>
</property>
</bean>
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
maybe you can use Sequoia (formerly C-JDBC) to cluster your schemas from diferent databases into a single logical database.
Related
I'm working on spring boot application, which already has a database connection established in its applicationContext.xml file and the necessary transaction manager and vendors etc.
I now need to connect the app to a second database. But I'm having issues with this. In my unit tests the connection is fine and can make simple queries to retrieve data, which is all I need it to do. However when I compile the app into a jar and run it, I get the following error
NoUniqueBeanDefinitionException: No qualifying bean of type "org.springframework.transaction.PlatformTransactionManager" available: expected single matching bean but found 2: transactionManager, transactionManager2
I have spent ages looking up how to solve this, and the suggested fixes I have found here , here and here have not worked.
I have one persistence.xml with two persistence units defined. And in my applicaitonContext.xml I defined two datasources, two transaction managers and two entity Manager Factories. I then use the #persitsencecontext and #Transactional("") annotations to say which persistence unit and managers to use, but I still get an error. I also added in the <qualifier> tag to the app context file, as I saw this as a suggested fix with the #transactional annotation, still no luck.
My code is below, can anyone spot an errors I have made, and why it may not be working as expected
applicationContext.xml
<bean id="dataSource1" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
<property name="url" value="..."/>
<property name="username" value="..."/>
<property name="password" value="..."/>
</bean>
<bean id="entityManagerFactory" name="proxy">
<property name="persistenceUnitName" value="proxy" />
<property name="persistenceUnitXmlLocation" value="classpath:META-INF/persistence.xml" />
<property name="dataSource" ref="dataSource1" />
<property name="jpaVendorAdapter" ref="hiberanteVendorAdapter" />
<property name="jpaProperties">
<props>
<prop key="hiberante.hbm2ddl.auto">valudate</prop>
</props>
</property>
</bean>
<bean id="hibernateVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="databasePlatform" value="org.hibernate.dialect.HSQLDialect" />
<property name="database" value="HSQL" />
<property name="showSql" value="true" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<qualifier value="transactionManager1" />
</bean>
<!-- Second datasource -->
<bean id="dataSource2" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
<property name="url" value="..."/>
<property name="username" value="..."/>
<property name="password" value="..."/>
</bean>
<bean id="entityManagerFactory2" name="proxy">
<property name="persistenceUnitName" value="proxy2" />
<property name="persistenceUnitXmlLocation" value="classpath:META-INF/persistence.xml" />
<property name="dataSource" ref="dataSource2" />
<property name="jpaVendorAdapter" ref="hiberanteVendorAdapter2" />
<property name="jpaProperties">
<props>
<prop key="hiberante.hbm2ddl.auto">valudate</prop>
</props>
</property>
</bean>
<bean id="transactionManager2" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory2" />
<qualifier value="transactionManager2" />
</bean>
<bean id="hibernateVendorAdapter2" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" />
<tx:annotation-driven/>
Implementation
#Repository
#Transactional("transactionManager2")
public class myDaoImpl extends GenericJPADao<Integer, Integer> implements ImyDao {
#PersistenceContext(unitName="proxy2")
protected EntityManager em;
}
SOLUTION
The accepted answer was the correct solution for me, but a few things to note. The beans have to point to their respective entityManagerFactory's and you need to be careful on which bean you set the autowire-candidate="false" on, as I set it on the incorrect one at first, and had transactions rolled back as a result. I think there could be cleaner solution to this, but as a quick fix it works fine
try this :
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" autowire-candidate="false">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="transactionManager2" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
If application is running and connected to Database-1. Through application I want to copy certain data from one Database (it can be Database-1 on any other) to another database. There can be 3-4 database. And schema is exactly same for all the database. Is it possible to do so?
I have read about "AbstractRoutingDataSource" here. But I don't wan't to connect to database during runtime. It should be after runtime.
my spring-config.xml contains bean for JdbcTemplate
<bean id="EnvJdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource">
<ref bean="envDataSource" />
</property>
</bean>
I have created bean for envDataSource (database 1)
<bean id="envDataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName"/>
<property name="url"/>
<property name="username"/>
<property name="password"/>
</bean>
Seems like you just need to create more beans, and inject them where needed, and call them when you need. This isn't that smart, but you don't need over engineer this.
<bean id="envDataSource1" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName"/>
<property name="url"/>
<property name="username"/>
<property name="password"/>
</bean>
<bean id="envDataSource2" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName"/>
<property name="url"/>
<property name="username"/>
<property name="password"/>
</bean>
<bean id="EnvJdbcTemplate1" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource">
<ref bean="envDataSource1" />
</property>
</bean>
<bean id="EnvJdbcTemplate2" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource">
<ref bean="envDataSource2" />
</property>
</bean>
There is a built in feature in Hibernate to support multiple schemas/databases. find it here
I have an application which used mix of JPA and JDBC. I have successfully done setup for JPA transaction using #Transactional annotation, but I am not able to make it work for JDBC.
My configuration looks like:
<bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource">
<property name="driverClassName" value="${database.driverClassName}"/>
<property name="url" value="${database.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
<property name="testOnBorrow" value="true"/>
<property name="testOnReturn" value="true"/>
<property name="testWhileIdle" value="true"/>
<property name="timeBetweenEvictionRunsMillis" value="1800000"/>
<property name="numTestsPerEvictionRun" value="3"/>
<property name="minEvictableIdleTimeMillis" value="1800000"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" >
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
<property name="persistenceUnitName" value="persistenceUnit"/>
<property name="dataSource" ref="dataSource"/>
</bean>
<bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
My code is :
#Test
#Transactional
public void testUpdateSQLwithParam() {
Object[] params = { "John","", "trol", "test", "M", "Place", "123456789",
"tom#domain.com" };
customQueryDao.insert("PERSON_INSERT_QUERY", params);
String sqlConstant = "PERSON_MASTER_UPADTE_QUERY";
params = new Object[]{ "Test", 8 };
customQueryDao.updateSQLwithParam(sqlConstant, params);
}
My JDBC code uses jdbcTemplate to execute queries. Please let me know how I can have JDBC transactions using #Transactional annotation. using jpatransactionmgr
You have 2 beans defined with the same id (transactionManager). Try it with a different ID, maybe like:
<bean id="jPATransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" >
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<bean id="dataSourceTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
This should work, you can also enable debugging on log4j to see transactions in your log files, here's what I have in my log4j.xml:
<!-- 3rdparty Loggers -->
<logger name="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<level value="debug" />
</logger>
I can see from you edit that you tried to fix the problem of multiple transaction manager. But I think you did not remove the good one ... From javadoc of JpaTransactionManager : This transaction manager also supports direct DataSource access within a transaction (i.e. plain JDBC code working with the same DataSource).
IMHO you should instead keep the JpaTransactionManager, and remove the DataSourceTransactionManager. (I have some code using plain JDBC mixed with Hibernate access with a single HibernateTransactionManager and transaction are correctly managed ...)
Tried to follow the pattern on apache dbcp examples, I understand everything except how and where the database properties come from and in which bean they have to be placed in application context.
I used Spring Data Source instead, but as I recall I configured it in hurry and I remember having difficulties with configuring the original dataSource provided by apache dbcp itself. So I happen to have time to face the problem and fulfill the original intent of using PoolingDataSource.
The reason I used Spring implementation is because it provides means of setting up the parameters to connect to database.
http://static.springsource.org/spring/docs/2.0.x/api/org/springframework/jdbc/datasource/DriverManagerDataSource.html
According to http://commons.apache.org/dbcp/apidocs/org/apache/commons/dbcp/PoolingDataSource.html
There are no methods to populate configuration like url or load driver.
I tried to track it through the object pools etc. , but got really lost.
Replying upfront: Yes, I don't want to use apache basicDataSource.
So now I am returning to the problem and can't really understand where to fetch the parameters? Driver? Url? It seems that url, pw and username are set on connection factory. But where to fetch postgresql driver to be loaded?
Please help to complete the configuration.
(using spring for configuration)
<!-- the one I want to use now -->
<bean id="dataSource" class="org.apache.commons.dbcp.PoolingDataSource">
<constructor-arg><ref bean="pool"/></constructor-arg>
</bean>
<!-- the one I used before as a workaround
<bean id="ds" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.postgresql.Driver"/>
<property name="url" value="jdbc:postgresql:postgres"/>
<property name="username" value="magicUserName"/>
<property name="password" value="magicPassword"/>
</bean> -->
<bean id="pool" class="org.apache.commons.pool.impl.GenericObjectPool">
<property name="minEvictableIdleTimeMillis"><value>300000</value </property>
<property name="timeBetweenEvictionRunsMillis"><value>60000</value </property>
</bean>
<bean id="dsConnectionFactory" class="org.apache.commons.dbcp.DataSourceConnectionFactory">
<constructor-arg><ref bean="dataSource"/></constructor-arg>
</bean>
<bean id="poolableConnectionFactory" class="org.apache.commons.dbcp.PoolableConnectionFactory">
<constructor-arg index="0"><ref bean="dsConnectionFactory"/ </constructor-arg>
<constructor-arg index="1"><ref bean="pool"/></constructor-arg>
<constructor-arg index="2"><null/></constructor-arg>
<constructor-arg index="3"><null/></constructor-arg>
<constructor-arg index="4"><value>false</value></constructor-arg>
<constructor-arg index="5"><value>true</value></constructor-arg>
</bean>
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<tx:annotation-driven transaction-manager="txManager" />
</beans>
I believe we are interested just in the first two, but I included everything just in case.
Seems to be there are many people using workarounds:
http://forum.springsource.org/showthread.php?10772-How-do-I-create-a-org-apache-commons-dbcp-PoolableConnection
You can config as below:
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="url" value="<put database connection url here>" />
<property name="username" value="XXXXXX" />
<property name="password" value="XXXXXXXX" />
<property name="driverClassName" value="<database driver here>" />
</bean>
<bean id="pool" class="org.apache.commons.pool.impl.GenericObjectPool">
<property name="minEvictableIdleTimeMillis"><value>300000</value></property>
<property name="timeBetweenEvictionRunsMillis"><value>60000</value></property>
</bean>
<bean id="dsConnectionFactory" class="org.apache.commons.dbcp.DataSourceConnectionFactory">
<constructor-arg><ref bean="dataSource"/></constructor-arg>
</bean>
<bean id="poolableConnectionFactory" class="org.apache.commons.dbcp.PoolableConnectionFactory">
<constructor-arg index="0"><ref bean="dsConnectionFactory"/></constructor-arg>
<constructor-arg index="1"><ref bean="pool"/></constructor-arg>
<constructor-arg index="2"><null/></constructor-arg>
<constructor-arg index="3"><null/></constructor-arg>
<constructor-arg index="4"><value>false</value></constructor-arg>
<constructor-arg index="5"><value>true</value></constructor-arg>
</bean>
<bean id="pooledDS" class="org.apache.commons.dbcp.PoolingDataSource"
depends-on="poolableConnectionFactory">
<constructor-arg><ref bean="pool"/></constructor-arg>
</bean>
And you can use "pooledDS" (PoolingDataSource) the same any orther DataSource.
Ortherwise, i think you should simply use BacsicDataSource, you still can config number of connections in pool by "initialSize" and "maxActive":
<bean id="basicDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="removeAbandoned" value="true"/>
<property name="initialSize" value="10" />
<property name="maxActive" value="50" />
</bean>
I have a web application using the Spring 3 + Hibernate JPA stack.
I would like to know if there is a way to have Hibernate to automatically discover #Entity annotated classes, so that I don't have to list them in the persistence.xml file.
My #Entity annotated classes "live" in a separate jar, located in the WEB-INF/lib of my web application.
This is a snippet from my Spring configuration file:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="mypersistence"/>
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true"/>
<property name="generateDdl" value="true"/>
<property name="databasePlatform" value="org.hibernate.dialect.DerbyDialect"/>
</bean>
</property>
</bean>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.apache.derby.jdbc.ClientDriver"/>
<property name="url" value="jdbc:derby://localhost:1527/library;create=true"/>
<property name="username" value="app"/>
<property name="password" value="app"/>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<bean id="persistenceAnnotation" class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
You can put the persistence.xml file inside the jar where your entities live. Don't need to specify anything then, it works automagically.
you can also specify your #Entity annotated classes in applicationContext.xml like this
<property name="packagesToScan">
<list>
<value>com.vattikutiirf.nucleus.domain</value>
<value>com.vattikutiirf.nucleus.domain.generated.secondtime</value>
</list>
</property>
The separate jar files to scan for entities are specified using <jar-file> elements in persistence.xml. So, if you entities are located in /WEB-INF/lib/entities.jar, you need
<jar-file>lib/entities.jar</jar-file>