I had done this programmatically at some point - that is creating two entity managers with different data sources and providing them for different services.
However now I am building a webApp using Spring. Thing is that I want to have two entity managers responsible for separate databases. So in my case, half of DAO's would be using emNumber1, and second half would be using emNumber2. Oh and totally different persistence units as I only need to read data from DB1 and then process it and store this data in DB2 in totally different entities.
I am well aware that this problem is and has been going around for sometime now but in different shapes and forms and so I am composing this question only because I could not understand the solutions that were presented withing those googled-up forum threads or they were not applicable to my case. In same cases I could not understand the solution or how to apply it in my case so really sorry for redundant question if it were to be solved by linking a solution from this very own site.
Here is how I find fit to configure a single transaction manager
<tx:annotation-driven transaction-manager="transactionManager" />
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource"
p:driverClassName="com.mysql.jdbc.Driver"
p:url="jdbc:mysql://localhost:3306/db"
p:username="dbuser"
p:password="dbuser"/>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="pu1"/>
<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.MySQL5Dialect"/>
</bean>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="dataSource" ref="dataSource"/>
</bean>
Then inside my dao:
public class SimpleDaoImpl implements SimpleDao {
#PersistenceContext
private EntityManager entityManager;
/* methods that use entity manager for transactions and data detcing */
}
So in case of two transaction managers with different data sources how would one specify what entity manager to inject into which DAO or is that impossible in Spring?
Here i have hibernate with two different data sources and i use #Qualifier to specify the session factory like this:
#Autowired
#Qualifier(value="sessionFactoryOne")
private SessionFactory sessionFactoryOne;
#Autowired
#Qualifier(value="sessionFactoryTwo")
private SessionFactory sessionFactoryTwo;
then i get the session from this guys.
In xml config i have two dataSource, sessionFactory and transactionManager, one for each DB.
Works fine ;)
You can do #PersistenceContext(unitName="pu1")
Related
We have configured multiple transaction managers:
<tx:annotation-driven transaction-manager="transactionManager1" />
<tx:annotation-driven transaction-manager="transactionManager2" />
<tx:annotation-driven transaction-manager="transactionManager3" />
<bean id="transactionManage1"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory1" />
</bean>
<bean id="transactionManager2"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory2" />
</bean>
<bean id="transactionManage3"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory3" />
</bean>
However,I don't see a name of transaction manager specified in #Transactional annotation in a service class. I am wondering which transaction manager will be used? The code is working and it looks like it used the first one - "transactionManager1" by default. Do I miss something?
I am wondering which transaction manager will be used?
The behaviour there is probably undefined, but it's most likely to use whichever <tx:annotation-driven> comes first in the context.
There's no reason you should need to do this. If you need fine-grained control over which tx manager to use, then you need to do it programmatically using something like TransactionTemplate. The #Transactional annotation is a convenience, but isn't as flexible as using the underlying API directly.
I am puzzled here. I wanted to implement optimistic locking in my spring hibernate program but the hibernate is not throwing StaleObjectStateException even though I open a data in separate browser and updated it separately.
My Dao looks like this:
public void update(User user) throws StaleObjectStateException{
sessionFactory.getCurrentSession().saveOrUpdate(user);
}
My Pojo look like this:
#Version#Temporal(TemporalType.TIMESTAMP)
#Column(name="timestamp", length=19)
public Timestamp getTimestamp() {
return this.timestamp;
}
Config.xml
<bean name="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
<property name="configurationClass">
<value>org.hibernate.cfg.AnnotationConfiguration</value>
</property>
</bean>
<tx:annotation-driven />
<bean name="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
One of my doubt why it is NOT throwing exception is that upon update, the other session timestamp is also updated since the data is persisted? Please help.
Perry
I see that you are using spring transaction manager. So I suppose somewhere you have #Transactional annotation that tracks your transactions. In this case I think that StaleObjectStateExceptionwill be thrown not on execution of update method of you class but when the transaction will be commited. And I also think that spring will wrap hibernate exception into HibernateOptimisticLockingFailureException. So you need to add throws declaration to the method that marked with #Transactional annotation.
If you do not have any transactional annotation than you need to add some or use manual transaction handling in Dao.
As it is mentioned in blogs/books (e.g. Java Transactions Design Strategies by Mark Richards), read operations must have the Propagation.SUPPORTS attribute.
In a simple Spring 3.1 MVC project with Hibernate 4.1 the scenario is:
Declarative transaction management using #Transactional
sessionFactory of org.springframework.orm.hibernate4.LocalSessionFactoryBean
Transaction manager of org.springframework.orm.hibernate4.HibernateTransactionManager
Service class with #Transactional(propagation=Propagation.REQUIRED)
Function of that Service class that only retrieves a resultset (performs read operation) with #Transactional(propagation=Propagation.SUPPORTS)
Function of read operation retieves the resultset using sessionFactory.getCurrentSession().get()
Of course, when a Controller executes the function of read operation, the exception "No Session found for current thread" is raised because a transaction is not started and a session is not obtained.
Based on the above configuration (while it is best e.g. non-invasive, less code etc) the Propagation.SUPPORTS attribute cannot be used unless a transaction is started before with Propagation.REQUIRED or Propagation.REQUIRES_NEW.
How do we use use Propagation.SUPPORTS for read operations without having to start a transaction e.g. with Propagation.REQUIRED before but still taking advantage the benefits of declarative transaction management?
Thank you in advance.
Coder, here is the configuration:
<tx:annotation-driven transaction-manager="txManager"/>
<context:component-scan base-package="com.myapps.service.impl" />
<bean id="txManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${db.driverClassName}" />
<property name="url" value="${db.url}" />
<property name="username" value="${db.username}" />
<property name="password" value="${db.password}" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mappingResources">
<list>
<value>.....</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${db.dialect}</prop>
<prop key="hibernate.format_sql">true</prop>
</props>
</property>
</bean>
I disagree with using SUPPORTS for read operations. Use REQUIRED.
A transaction is needed anyway to perform every database operation
Doing several small transactions to read several things at once won't benefit from the first-level cache
There won't be any isolation between all the subsequent reads, meaning that something not visible to the first read might become visible for the second one
you'll get lazy loading exceptions when traversing associations
Transaction is not always required for Propagation.SUPPORTS.
Propagation.SUPPORTS: Support a current transaction, execute non-transactionally if none exists.
I have a project with spring and hibernate in GWT,
I am using below applicationcontext.xml,
I was just looking for some best approach of making this file
like all the annotated classes below i.e entity.user, entity.secretQuestion and many more , they all get called when my application runs even if i don't need them , which i guess makes my application quite slow,
so is it possible that only the class which i am calling is getting load in applicationcontext.xml and if yes then would it be a better approach as well ?
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.cricsite.persistence.entity.User</value>
<value>com.cricsite.persistence.entity.SecretQuestion</value>
</list>
</property>
</bean>
<bean id ="ManagerAdmin" class= "com.persistence.MySQLRdbHelper">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
You might be looking for something called "lazy loading"
Please take a look at these threads;
Help needed with Spring/Hibernate Lazy-loading
What is lazy loading in Hibernate?
how does spring allow for lazy-loading?
I have the following config.
<bean id="abcManager" parent="TxProxyTemplate">
<property name="target">
<bean class="com.x.y.AbcManagerImpl">
<property name="abcDAO" ref="abcDAO"/>
<property name="xyzManager" ref="xyzManager"/>
</bean>
</property>
</bean>
<bean id="xyzManager" parent="TxProxyTemplate">
<property name="target">
<bean class="com.x.y.XyzManagerImpl">
<property name="abcDAO" ref="abcDAO"/>
<property name="anotherManager" ref="anotherManager"/>
</bean>
</property>
</bean>
<bean id="anotherManager" parent="TxProxyTemplate">
<property name="target">
<bean class="com.x.y.AnotherManagerImpl">
<property name="abcDAO" ref="abcDAO"/>
<property name="oneMoreManager" ref="oneMoreManager"/>
</bean>
</property>
</bean>
What is the issue with the following configuration? will having the same DAO at the different levels cause concurency issues?
We found that we get lots of weblogic connection releases when we have high load.
How is this related to the connection release issue?
We use Hibernate for DAO operations.
First, analyse the logs to see when spring creates and closes transactions.
Set the logger for org.springframework.transaction to DEBUG for this.
Next my guess is you need to examine your #Transactional annotations (which I assume you use on your managers (=services?). Make sure the propagation is set correctly because this might be related to your issue (hard to say without seeing your manager's code of course).
To answer your question directly:
What is the issue with the following configuration? will having the same DAO at the different levels cause concurency issues?
Nothing, and no. I don't see anything wrong with this. Not sure what you mean about 'same DAO' - you don't have the same DAO. You have the same parent, but 3 distinct DAOs.
If you're asking, then, why is weblogic closing your DB connections before your transaction completes, we wouldn't be able to answer that with the information above.