Multiple transaction managers in spring and select one at runtime - java

For each client, I have separate databases but business logic and tables are same for each client. I want common service and dao layer for each client. In dao, I select datasource based on logged user client. In #Transactional, I have to pass bean id of transaction manager. How to make common service layer with #Transactional annotation.
Same question is here
Multiple transaction managers - Selecting a one at runtime - Spring
Choose between muliple transaction managers at runtime
but nobody reply

If you want to create a database connection dynamically, then have a look at this SO post.
From the post linked : Basically in JDBC most of these properties are not configurable in the
API like that, rather they depend on implementation. The way JDBC
handles this is by allowing the connection URL to be different per
vendor.
So what you do is register the driver so that the JDBC system can know
what to do with the URL:
DriverManager.registerDriver((Driver)
Class.forName("com.mysql.jdbc.Driver").newInstance());
Then you form
the URL:
String url =
"jdbc:mysql://[host][,failoverhost...][:port]/[database][?propertyName1][=propertyValue1][&propertyName2][=propertyValue2]"
And finally, use it to get a connection:
Connection c = DriverManager.getConnection(url);
In more
sophisticated JDBC, you get involved with connection pools and the
like, and application servers often have their own way of registering
drivers in JNDI and you look up a DataSource from there, and call
getConnection on it.
In terms of what properties MySQL supports, see here (The link is dead).
EDIT: One more thought, technically just having a line of code which
does Class.forName("com.mysql.jdbc.Driver") should be enough, as the
class should have its own static initializer which registers a
version, but sometimes a JDBC driver doesn't, so if you aren't sure,
there is little harm in registering a second one, it just creates a
duplicate object in memeory.
I don't know if this will work, since I have not tested it, but you
could try.
Now what you could do is, use the #Transactional annotation on top of the DAOs without specifying any values (That works). Now in your DAO classes, instead of injecting any DataSource bean, create your own dataSource dynamically as specified in the above link and then either inject that dependency at runtime, use getter setter methods, or just use the new keyword. I hope that'd do the trick.
NOTE: I have not tested it myself yet, so if this works, do let me know.

You do not need to configure and switch between multiple transaction managers to accomplish your end goal. Instead use the Spring provided org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource mechanism.
Detailed examples can be found here :
https://spring.io/blog/2007/01/23/dynamic-datasource-routing/
http://howtodoinjava.com/spring/spring-orm/spring-3-2-5-abstractroutingdatasource-example/

Related

Is JPA an appropriate ORM for this scenario?

We have a central database for accounts. It contains login information, and a field called database profile. The database profile indicates what database connection should be used for the account. For example, we would have Profile1, Profile2, Profile3... ProfileN
If a user is indicated to have Profile1, they would be using a different database than a user who is indicated to be a part of Profile2.
My understanding of JPA is that you would need a new EntityManagerFactory for each Profile (Persistence Unit), even though the databases all have the same schema, just different connection information. So if we ended up having 100 profiles we would have 100 Entity Manager Factories, which doesn't seem ideal.
I've looked into the EntityManagerFactory, and it doesn't seem to let you change the database connection options.
Is my only option to have N EntityManagerFactory's, and if so would their be be any major consequences to this (such as bad performance)?
Thanks for any advice.
The kinds of things you're talking about are getting out of the scope of the JPA abstraction. Things like specific connection management are generally more provider specific. For example, with Hibernate SessionFactory you can certainly create new sessions from an aribtraty JDBC connection. There would be pitfalls to consider such as ID generation schemes (you'll probably have to use sequences generated in the DB), and you're basically hooped for L2 caching, but with careful programming it could be made to work.
Just use javax.persistence.Persistence#createEntityMananagerFactory(String,Map), and provide in the Map the connection parameters. Cache the EMF, and use the connections judiciously, don't mix n match object from the different EMFs.
If you are using spring then I know there is a way to dynamically switch the DataSource. Find more information here

How to pass around JDBC connection without using Spring/JPA/Hibernate

We have a Java J2EE application that was using individual web service calls for each database row insert/update. That turned out to be WAY too slow. They have brought me in to "quickly" fix it. I plan to convert all the web service calls to plain JDBC. To do that, I need to get a JDBC connection from the pool and then use it in multiple different methods. I need to use the same JDBC connection in multiple DAOs to string it all together into a single database transaction. I can explicitly pass around the JDBC connection to each DAO that needs it, but that would require me to change a LOT of method signatures, plus a LOT of unit tests (which goes against the "quickly" part).
I am trying to come up with a good way put the JDBC connection somewhere and then just grab it in the methods that need it without having to explicitly pass it around everywhere. We can't use Spring, JPA, or Hibernate on this project because the support team won't support those technologies. I can put the JDBC connection into an EJB, but I am not sure how reliable that would be. I could create a custom Singleton to manage database connections for each user (session?), but I would have to be careful about thread safety. If anyone has tried to do something like this before, I would appreciate some advice.
You could use a ThreadLocal. Have the entry point set it up and than the DAOs
class ConnectionUtil {
public static final ThreadLocal<Connection> connection = new ThreadLocal<Connection>();
}
public Return method(Args arg) {
ConnectionUtil.connection.set(newConnection());
try {
...
} finally {
ConnectionUtil.connection.remove();
}
}
Pretty ugly, but that seems to be what your boss wants.
Use Apache Commons DBCP. It's the Connection Pool project from Apache, and what's used internally in many engines.
We have done that before (5 years ago or so on an IBM WebSphere).
We wrote an own pool and stored the jdbc-connections in a hashtable with the sessionID. The only pitfall was to close the connection on sessionend and return it to the pool (we did that with a sessionlistener). If one user session connects only to one jdbc-connection, the thread safety is inherited. So the singleton approach does definitly work.
Our performance gain was awful.
Additionally what I have done for DAOs in this is not to pass the connection in the method signature but in the Constructor instead. Then I hold the object that originally creates the connection responsible to close it.

Sharing a Spring transaction between hibernate & JdbcTemplate within a AbstractTransactionalTestNGSpringContextTests

I'm running a test within a subclass of AbstractTransactionalTestNGSpringContextTests, where I execute tests over a partial Spring context. Each test runs within a transaction, which is rolled back at the end to leave the database unchanged.
One test writes to the database through Hibernate, while another reads from the same database using the JdbcTemplate, with both share the same datasource.
I'm finding that I can't see the hibernate updates when querying through the JdbcTemplate. This does make some sense, as each is presumably getting its own connection from the connection pool and so is operating within its own transaction.
I've seen indications that it's possible to get the two to share a connection & transaction, but am not clear of the best way to set this up, especially with the involvement of the connection factory. All these components are declared as Spring beans. Can anyone give me any pointers?
Edit:
Well I've gone to the trouble of actually reading some documentation and the HibernateTransactionManager class states that this is definitely possible: "This transaction manager is appropriate for applications that use a single Hibernate SessionFactory for transactional data access, but it also supports direct DataSource access within a transaction (i.e. plain JDBC code working with the same DataSource)...".
The only requirement appears to be setting the datasource property, which isn't otherwise required. Having done that, though, I'm still not seeing my changes shared before the transaction has been committed. I will update if I get it working.
The Spring bean that writes has to flush its changes in order for the bean that reads to see them.

Spring-Hibernate used in a webapp,what are strategies for Thread safe session management

I'm developing a web app with Spring and Hibernate and I was so obsessed by making he application thread safe and being able to support heavy load that based on my boss recommendation I end up writing my own session and a session container to implement a session per request pattern. Plus I have a lot of DAOs and me not willing to write the same save method for all the DAOs I copy paste this Hibernate GenericDAO (I can't tell it's the same thing because at the time hibernate wasn't owned by jboss) and do the plumbing stuff, and under pressure, all become quickly complicated and on production, the is StaleObjectException and duplicated data right, and i have the feeling that it's time to review what I've done, simplify it and make it more robust for large data handling. One thing you should know is that one request involves many DAO's.
There is quartz running for some updates in the database.
As much as I want to tune everything for the better I lack time to do the necessary research plus Hibernate is kind of huge (learning).
So this is it, I'll like to borrow your experience and ask for few question to know what direction to take.
Question 1 : is Hibernate generated uuid safe enough for threading environment and avoiding StaleObjectException?
Question 2 what are best strategy to use hibernate getCurrentSession in threadSafe scenario (I've read about threadlocal stuff but didn't get too much understanding so didn't do it)
Question 3 : will HIbernateTemplate do for the simplest solution approach?
Question 4 : what will be your choice if you were to implement a connection pool and tuning requirement for production server?
Please do no hesitate to point me to blogs or resources online , all that I need is a approach that works for my scenario. your approach if you were to do this.
Thanks for reading this, everybody's idea is welcomed...
I'm developing a web app with Spring and Hibernate and I was so obsessed by making he application thread safe and being able to support heavy load that based on my boss recommendation I end up writing my own session and a session container to implement a session per request pattern.
You should just drop all this code and use Spring/Hibernate APIs instead: less bugs, less maintenance.
I copy paste this Hibernate GenericDAO (I can't tell it's the same thing because at the time hibernate wasn't owned by jboss) and do the plumbing stuff, and under pressure, all become quickly complicated (...)
You can use a GenericDao and inject the required stuff with Spring.
Question 1: is Hibernate generated uuid safe enough for threading environment and avoiding StaleObjectException?
To strictly answer your question, here is what Reference Guide writes about the uuid generator:
5.1.4.1. Generator
...
uuid
uses a 128-bit UUID algorithm to
generate identifiers of type string
that are unique within a network (the
IP address is used). The UUID is
encoded as a string of 32 hexadecimal
digits in length.
So I consider it as safe. But I think your StaleObjectException are unrelated (it's another problem).
Question 2: what are best strategy to use hibernate getCurrentSession in threadSafe scenario (I've read about threadlocal stuff but didn't get too much understanding so didn't do it)
The best strategy is to just use it, sessionFactory.getCurrentSession() will always give you a Session scoped to the current database transaction aka a "contextual session". Again, quoting the Reference Documentation:
2.5. Contextual sessions
Most applications using Hibernate need
some form of "contextual" session,
where a given session is in effect
throughout the scope of a given
context. However, across applications
the definition of what constitutes a
context is typically different;
different contexts define different
scopes to the notion of current.
Applications using Hibernate prior to
version 3.0 tended to utilize either
home-grown ThreadLocal-based
contextual sessions, helper classes
such as HibernateUtil, or utilized
third-party frameworks, such as Spring
or Pico, which provided
proxy/interception-based contextual
sessions.
(...)
However, as of version 3.1, the
processing behind
SessionFactory.getCurrentSession()
is now pluggable. To that end, a new
extension interface,
org.hibernate.context.CurrentSessionContext,
and a new configuration parameter,
hibernate.current_session_context_class,
have been added to allow pluggability
of the scope and context of defining
current sessions.
See the Javadocs for the
org.hibernate.context.CurrentSessionContext
interface for a detailed discussion of
its contract. It defines a single
method, currentSession(), by which
the implementation is responsible for
tracking the current contextual
session. Out-of-the-box, Hibernate
comes with three implementations of
this interface:
org.hibernate.context.JTASessionContext:
current sessions are tracked and
scoped by a JTA transaction. The
processing here is exactly the same as
in the older JTA-only approach. See
the Javadocs for details.
org.hibernate.context.ThreadLocalSessionContext:
current sessions are tracked by thread
of execution. See the Javadocs for
details.
org.hibernate.context.ManagedSessionContext:
current sessions are tracked by thread
of execution. However, you are
responsible to bind and unbind a
Session instance with static methods
on this class: it does not open,
flush, or close a Session.
(...)
There is no need to implement your own ThreadLocal-based solution nowadays, don't do that.
Question 3 : will HIbernateTemplate do for the simplest solution approach?
Well, the HibernateTemplate is not deprecated but it is not recommended anymore and I prefer to implement template-less DAOs:
public class ProductDaoImpl implements ProductDao {
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public Collection loadProductsByCategory(String category) {
return this.sessionFactory.getCurrentSession()
.createQuery("from test.Product product where product.category=?")
.setParameter(0, category)
.list();
}
}
Where the SessionFactory is injected by Spring. I suggest to read So should you still use Spring's HibernateTemplate and/or JpaTemplate?? for complete background and also the whole section 13.3. Hibernate in the Spring documentation on ORM Data Access.
Question 4 : what will be your choice if you were to implement a connection pool and tuning requirement for production server?
Hmm... What? I would never implement my connection pool but use the one from my application server. Maybe you should clarify this question.
Update: In production, I wouldn't use Hibernate built-in connection pool but configure Hibernate to use an application server provided JNDI datasource (and thus the application server connection pool). From the documentation:
3.3. JDBC connections
...
Here is an example hibernate.properties file for an application server provided JNDI datasource:
hibernate.connection.datasource = java:/comp/env/jdbc/test
hibernate.transaction.factory_class = \
org.hibernate.transaction.JTATransactionFactory
hibernate.transaction.manager_lookup_class = \
org.hibernate.transaction.JBossTransactionManagerLookup
hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
JDBC connections obtained from a JNDI datasource will automatically participate in the container-managed transactions of the application server.

how to pass user created connection to hibernate

is there any way, to restrict hibernate not to create connection of its own(what we define in hibernate.properties or hibernate.cfg.xml), instead i can create and pass the connection to hibernate for further processing.
The problem is that i need to set the ApplicationContext on the connection given that the i am using oracle connection. I know how to create a connection and set the applicationContext on to it.. but the problem is that i don't know how to force hibernate to use the connection that i have created.. Please help..
The right way to do this would be to use a custom implementation of o.h.c.ConnectionProvider. In the getConnection() method, you will have the opportunity to cast the regular Connection into an OracleConnection and to do dark voodoo with it before to return it.
This interface has several implementations that you can extend to ease the work, depending on how you get the initial connection (e.g. from a Datasource).
This post in the Hibernate forums shows an implementation that could be used as a kickoff example (the poster is also doing black magic with an OracleConnection so it's a good example).
Have a look at this section of the Hibernate manual.

Categories