1

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?

Community
  • 1
  • 1
Drizzt321
  • 993
  • 13
  • 27
  • Forgot to add, Javers seems to request a connection for every query it does during a javers.commit(), and with it grabbing way more properties than I want it to it seems to require another Connection for each query about each property, thus eats up the 100 connections in the pool on the first javers.commit(). – Drizzt321 Mar 30 '16 at 19:37

2 Answers2

2

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.

Drizzt321
  • 993
  • 13
  • 27
  • Can you please elaborate on how this solved your problem and where you implemented it? I personally don't manage my own ConnectionProvider and just rely on JPA/Hibernate to do everything "auto-magically". – buddyp450 Jul 13 '21 at 20:01
  • So I'm using MyBatis, which isn't a fully blown ORM like JPA/Hibernate is, so it's not relying on them to handle any transactions. I did my own annotations and Aspects to detect and start transactions, and then when leaving properly commit/rollback the transactions. Not sure how much that helps you, although you can probably add in a hook for the Transaction Commit/Rollback in Hibernate (I think you can), and grab the current DataSource and properly use it with JaVers to update/commit JaVers transaction log stuff. – Drizzt321 Jul 29 '21 at 23:45
0

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.

Bartek Walacik
  • 3,386
  • 1
  • 9
  • 14
  • Ah, literally just as I was posting my reply. Turns out Spring has a utility to grab the current connection for the current Transaction so Javers now can participate in it fully and seamlessly with the spring integration TransactionalJaversBuilder. – Drizzt321 Mar 30 '16 at 22:12