How Spring transaction is mapped to underlying database connection - spring

I am trying to understand in background how transaction is mapped to jdbc connection i.e one jdbc connection can be parallely used for multiple spring transactions at the same time or one connection is totally reserved for one transaction at a given time and only released after transaction is complete.

I my opionion one of the best way to understanding how Spring managed transactions is reading Transaction Management Reference Doc.

Related

Spring Boot DB connection release mode

Is there a way to control database connection release strategy in Spring Boot? Something like Hibernate's ConnectionReleaseMode?
My test code would be rougly following:
INSERT query
HTTP call
UPDATE query
INSERT and UPDATE queries are their own methods in a repository bean (either extending CrudRepository, or as a Mybatis #Mapper). HTTP call is in it's own bean.
Now my service bean is where I experiment with different #Transactional settings as my ultimate goal is to have these three steps executed within a single transaction.
The problem is, the HTTP call can take hundreds of millis and Spring is holding the database connection during that time. This quickly leads to an empty connection pool, while the connections themselves are idle.
I have done the same experiments with default configuration using spring-boot-starter-data-jpa and also using mybatis-spring-boot-starter.
The only thing which got me closer to my goal was setting spring.jpa.open-in-view=false for data-jpa, which would release db connections in case of not using #Transactional at all or with propagation set to NEVER. It doesn't work if it's all wrapped in a transactin though.
I'm feeling like I'm missing some vital part of the transaction concept in Spring. Though the Spring reference docs mentions release mode only in relation to JTA transaction manager + JEE container + Hibernate.
Transactions are bound to a connection/session so you can't release the connection in the middle of a transaction. You have to finish the transaction to close/release the connection. Keep in mind that a transaction could abort at any time, and since the HTTP call is not "part of" the transaction, but just runs while the transaction is in progress, it won't help you to keep the transaction open while the HTTP call is running. I'd suggest you go with one of the following solutions:
Use a circuit breaker to cancel the HTTP call if it hits a timeout to have an upper bound for how long a connection/transaction can be open/held
Move the HTTP call out of the transaction, either before or after the transaction
Use two database transactions
Note that you could use a transactional Job Scheduler to schedule a job in the first TX. The job could then, with at least once semantics, try to invoke the HTTP call and then continue with the second transaction or do some compensation if something fails.

Javers is grabbing all of my available Connections

One other thing I'm finding, is that it appears that Javers is grabbing all of the available Connections out of my connection pool (created via Spring DataSourceBuilder). I'm not using Hibernate/JPA, just straight JDBC via JdbcTemplate and mostly MyBatis for my entity queries.
I've added a logging statement to my ConnectionProvider for Javers, and at the start of the application when it queries for the schema, it pulls 4 connections to check for each of the tables, and then never returns any of them even after the commit from the PlatformTransactionManager.
I understand from https://stackoverflow.com/a/35147884/570291 that it's supposed to participate in the same connection as the current Transaction. Since I'm not using Hibernate/JPA, does that mean I need to implement the connection tracking/etc from MyBatis to the Javers ConnectionProvider to return the same connection (if there is one), and then handle closing (returning to the pool) of that connection at the end of the transaction?
I found DataSourceUtils.getConnection(DataSource) which is a Spring utility class to get a connection from the given DataSource including if it's tied to a current transaction or not as appropriate. Using that in the ConnectionProvider looks like it's done the trick of keeping the connection for the existing transaction.
JaVers won't return connections to application's connection pool for the same reason as it won't call sql commit or rollback.
Managing connactions and transactions is the application's responsibility, not JaVers. We call it passive mode, from Javers doc:
- JaVers doesn’t create JDBC connections on its own and uses connections provided by an application (via ConnectionProvider.getConnection()).
- JaVers philosophy is to use application’s transactions and never to call SQL commit or rollback commands on its own.
Thanks to this approach, data managed by an application (domain objects) and data managed by JaVers (object snapshots) can be saved to SQL database in one transaction.
In JaVers project there is no mybatis support, so you need to implement ConnectionProvider for mybatis on your own.
Proper implementation of ConnectionProvider shouldn't create new sql connection for every getConnection() call. It should return the connection which underlies current application's transaction. Typically, it's implemented using ThreadLocal.
As you mentioned, ConnectionProvider should handle committing transactions and closing connections.

JTA Transaction with multiple participants

I'm having trouble finding a simple example of a JTA transaction spanning multiple resources (e.g. two databases, a database and a JMS queue, etc.)
I've spent a lot of time reading up on this and have working samples of doing a JTA transaction with a JMS queue, and a JTA transaction over a JDBC database driver. I just can't seem to find anything on making both the JMS queue and the JDBC database part of the same JTA transaction.
Can anyone provide a brief sample or a link to something that does demonstrate how to use the JTA API for this purpose?
For a JTA transaction to coordinate amongst JMS and JDBC resources, the following is required:
XAConnectionFactory - a JMS XA-compliant connection factory must be available in JNDI; the specific one to use depends on your application server/container.
XA-compliant JDBC driver - the driver must be XA, most databases provide one, and the connection must support READ_COMMITTED isolation level, anything less won't be sufficient.
Aside from that, if you're using an app server, the container will handle transactions automatically if you're using message driven beans and XA-compliant drivers.
Check these links for exmaples:
http://blog.inflinx.com/2010/04/08/spring-jta-jpa-jms/
http://www.oracle.com/technetwork/java/faq-140431.html#relship_transac

Tomcat 7 connection pool / JPA : Getting a specific connection

I am using JPA together with the Tomcat 7 connection pool.
How is it possible to specify that the EntityManager injected (by Spring in this case) into a data access object should use a specific connection from the pool, not one taken at random?
In other words, the requirement is to initialize specific connections in the pool (so these connections see the database pre-configured in various states), to then 'label' these connections and to then get EntityManager / the transaction to use the connection with a specific label.
I know that Oracle UCP offers similar functionality, but we have had issues with that so we want to do the same thing with the Tomcat pool.
Thanks !

Sharing JMS and Hibernate transactions in a Spring MDB using Oracle Streams AQ?

I'm using Oracle 11g for my database and its Oracle Streams AQ feature as JMS implementation.
For all I know, it should be possible to implement a Spring based message-driven POJO (MDP) that uses the same data source for both transactional data access and JMS transactions -- all without XA-Transactions (IIRC, this was marketed as a feature of SpringSource Advanced Pack for Oracle).
Is this possible using Hibernate as well? Ideally, my MDP would start a JMS transaction and read a message from a queue, then re-use the transaction for data access through Hibernate. If anything goes wrong, the JMS and database transaction would both be rolled back, without using 2-phase commit (2PC).
I'm not much of a transaction guru, so before I start digging deeper, can anyone confirm that this is possible and makes sense as well?
Update:
What I want is an implementation of the Shared Transaction Resource pattern. The sample code demonstrates it for ActiveMQ and JDBC, but I need to use Oracle Streams AQ and Hibernate.
Update2:
The SpringSource Advanced Pack for Oracle has been open sourced as part of Spring Data JDBC and it "provides the option of using a single local transaction manager for both
database and message access without resorting to expensive distributed 2-phase commit
transaction management".
2PC shouldn't be necessary, as you say, since the appserver should take care of it. However, you'll pretty much have to use JTA (i.e. JavaEE container) transactions, rather than vanilla DataSource transactions, since JMS only works with JTA.
This isn't a big deal, it's just a bit more fiddly:
Your Spring config should use
<jee:jndi-lookup/> to get a
reference to your container's
DataSource, and you inject that
data source into your spring-managed
hibernate SessionFactory.
You then need to introduce a transaction manager into the context (<tx:jta-transaction-manager/> should work in most app-servers).
In your Spring JMS MessageListenerContainer, plug the above transaction manager reference into it.
Does that all make sense, or should I elaborate? This setup should ensure that the container-managed transactions are held across JMS and Hibernate interactions.

Resources