I have a spring (version 3.2.15) application that uses more than one connection in a transactional method.
My use case is:
Call to transactional method (which opens one connection)
Query for an entity (which opens and closes another connection)
Persist the entity
End of the method (closes the first connection)
The problem is that I have a limited number of connections, and I need to ensure that only one connection is used per transactional method. This problem causes a dead lock in my application because there are much more transactions opened than the number of connections available.
Is there any way that I can use the same connection spring uses to maintain the transaction on my method? I have already tried the hibernate option hibernate.connection.release_mode in after_statement mode, but an error occurs when hibernate is trying to commit the transaction.
I've read the spring transaction documentation but I cannot figure out how to configure spring to behave this way.
Related
We're facing huge versions upgrade of the codebase, in that codebase we're using hibernate and jdbi to connect to a postgres 12 db.
JDBI version is not changed in this upgrade, Hibernate version was 5.1.5.Final and has been updated to 5.3.10.Final.
Now I've a lot of trouble with connection that remain open, I report some tests that I've done (the problem are on reading).
In the previous version I do three query through hibernate (and for each one i use close method on entity manager after I get the result) and them all remain in idle in transaction, then I perform a jdbi query and all hibernate sessions will disappear.
With the new version, same test, I've to increase connection pool size through
<property name="hibernate.connection.pool_size" value="3"/></properties>
but connections remain always idle in transaction and never been closed.
I've noticed that adding commit method before closing the entity manager will leave a number of connection open equals to the number that I've placed as pool size.
Can someone explains how connection works in hibernate? Especially why in the previous version connections were closed automatically after doing a jdbi query.
I have a non-web application that will run in background, during its run period I don't need any transactions. I must ensure that every jdbc operation should be automatically committed immediately, but spring jpa doesn't allow that happened.
How could I avoid TransactionRequiredException without transaction opened ??
Open a transaction. If you don't need an extended transaction and just want to do a quick update and commit it, you still need a transaction; just put #Transactional on the one method (or grab an EntityManager) and finish everything right there.
We are migrating a JDBC based application to JPA and EJB3. Our old application used the Connect#setClientInfo API to record the current user name as part of the client info:
http://download.oracle.com/javase/6/docs/api/java/sql/Connection.html#setClientInfo%28java.lang.String,%20java.lang.String%29
We need to do something similar in the EJB3 project. How?
We can use EJB3 interceptors around the EJB service calls in order to capture the current user and set it as info on the datasource. However, I see problems with this. I think there is no guarantee when the JPA flush() occurs. If you set the client info in an interceptor, make some updates, and then return, the flush() and actual database write may not occur until well after your bean (and interceptor) are out of scope. Is this correct?
I believe JPA and EntityManagers are abstractions over the connection, and you cannot reliable set the client info on the connection. True or false?
What JPA provider are you using?
EclipseLink has support for user based connection, Oracle proxy connections and VPD. EclipseLink also defines Session and connection level events that allow you to set configuration on the JDBC connection.
See,
http://wiki.eclipse.org/EclipseLink/Examples/JPA/Auditing
when using hibernate with spring, can someone explain how the session unit of work and transactions are handled?
is the transaction started at the beginning of the page request, and committed at the end?
can I have multiple db calls per request, that each have different transaction levels? e.g. some are left as default, while others are read-uncommitted?
is the transaction started at the beginning of the page request, and committed at the end?
In a web application, opening / closing the Session is usually done using the "Open Session in View" pattern. Spring comes with a OpenSessionInViewFilter or an OpenSessionInViewInterceptor for this. Both make Hibernate Sessions available via the current thread, which will be autodetected by transaction managers. It is suitable for service layer transactions via HibernateTransactionManager or JtaTransactionManager as well as for non-transactional execution (if configured appropriately).
Transaction demarcation is usually done at the service methods level, using Spring AOP to wrap them inside transactions.
can I have multiple db calls per request, that each have different transaction levels? e.g. some are left as default, while others are read-uncommitted?
You can have nested transactions with different isolation levels. Refer to the Transaction Management chapter.
It's usually configured declaratively with aspect oriented programming (AOP). You can define what beans, classes, packages or methods require transactions and Spring will provide it in a fashion similar to EJBs. Thanks to AOP you have full control over what exactly and how is wrapped into transactions.
Read more about it here: http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html#transaction-declarative
to your questions:
1-is the transaction started at the
beginning of the page request, and
committed at the end?
Not exactly. the usual workflow of spring MVC is:
requestDispatcher->Controller->Service call(transaction starts and ends here)
Services may invoke Daos, Daos will talk to Datastore via Hibernate.
A transaction can continue living after the http response. e.g. service run in a thread.
2-can I have multiple db calls per
request, that each have different
transaction levels? e.g. some are left
as default, while others are
read-uncommitted?
Yes certainly you can.
let's say, your application does a migration job. a request says "start migration!" Then your service will read data via source database, and do some magic base on your migration logic, finally write to target database, and commit the transaction.
I have an application - more like a utility - that sits in a corner and updates two different databases periodically.
It is a little standalone app that has been built with a Spring Application Context. The context has two Hibernate Session Factories configured in it, in turn using Commons DBCP data sources configured in Spring.
Currently there is no transaction management, but I would like to add some. The update to one database depends on a successful update to the other.
The app does not sit in a Java EE container - it is bootstrapped by a static launcher class called from a shell script. The launcher class instantiates the Application Context and then invokes a method on one of its beans.
What is the 'best' way to put transactionality around the database updates?
I will leave the definition of 'best' to you, but I think it should be some function of 'easy to set up', 'easy to configure', 'inexpensive', and 'easy to package and redistribute'. Naturally FOSS would be good.
The best way to distribute transactions over more than one database is: Don't.
Some people will point you to XA but XA (or Two Phase Commit) is a lie (or marketese).
Imagine: After the first phase have told the XA manager that it can send the final commit, the network connection to one of the databases fails. Now what? Timeout? That would leave the other database corrupt. Rollback? Two problems: You can't roll back a commit and how do you know what happened to the second database? Maybe the network connection failed after it successfully committed the data and only the "success" message was lost?
The best way is to copy the data in a single place. Use a scheme which allows you to abort the copy and continue it at any time (for example, ignore data which you already have or order the select by ID and request only records > MAX(ID) of your copy). Protect this with a transaction. This is not a problem since you're only reading data from the source, so when the transaction fails for any reason, you can ignore the source database. Therefore, this is a plain old single source transaction.
After you have copied the data, process it locally.
Setup a transaction manager in your context. Spring docs have examples, and it is very simple. Then when you want to execute a transaction:
try {
TransactionTemplate tt = new TransactionTemplate(txManager);
tt.execute(new TransactionCallbackWithoutResult(){
protected void doInTransactionWithoutResult(
TransactionStatus status) {
updateDb1();
updateDb2();
}
} catch (TransactionException ex) {
// handle
}
For more examples, and information perhaps look at this:
XA transactions using Spring
When you say "two different databases", do you mean different database servers, or two different schemas within the same DB server?
If the former, then if you want full transactionality, then you need the XA transaction API, which provides full two-phase commit. But more importantly, you also need a transaction coordinator/monitor which manages transaction propagation between the different database systems. This is part of JavaEE spec, and a pretty rarefied part of it at that. The TX coordinator itself is a complex piece of software. Your application software (via Spring, if you so wish) talks to the coordinator.
If, however, you just mean two databases within the same DB server, then vanilla JDBC transactions should work just fine, just perform your operations against both databases within a single transaction.
In this case you would need a Transaction Monitor (server supporting XA protocol) and make sure your databases supports XA also. Most (all?) J2EE servers comes with Transaction Monitor built in. If your code is running not in J2EE server then there are bunch of standalone alternatives - Atomicos, Bitronix, etc.
You could try Spring ChainedTransactionManager - http://docs.spring.io/spring-data/commons/docs/1.6.2.RELEASE/api/org/springframework/data/transaction/ChainedTransactionManager.html that supports distributed db transaction. This could be a better alternative to XA