#EnableJpaRepositories.enableDefaultTransactions = false not working - spring-data

The JavaDoc reads
Configures whether to enable default transactions for Spring Data JPA repositories. Defaults to true. If disabled, repositories must be used behind a facade that's configuring transactions (e.g. using Spring's annotation driven transaction facilities) or repository methods have to be used to demarcate transactions.
I debugged into the framework, and there it just creates a transaction if none exists, even with enableDefaultTransactions = false.
As far as I can see, Spring Data JPA Repositories are pre-configured with #Transactional(readOnly=true) (see SimpleJpaRepository), which leads to nobody noticing when a programmer forgot to properly annotate his service or job with the proper #Transactional because Spring Data JPA creates a transaction for every repository method that's called.
I wanted to disable it. First try was putting a #Transactional(MANDATORY) on my repository super interface. That wasn't working.
Then I noticed "enableDefaultTransactions" in the #EnableJpaRepositories annotation. I set it to false, but nothing changed. The JavaDoc lead me to believe that it would do exactly what I wanted: to remove the default transaction support and throw an exception when using a repository without already being in a transaction context.
Am I wrong? Is this a bug? Is enableDefaultTransactions intended any other way?
Using spring data jpa 1.9.0.RELEASE.

The intention of enableDataTransactions=false is to remove the default transaction management from the implementation (I guess from SimpleJpaRepository). It will behave as if no #Transactional was specified. Then you can control transactions in the service layer.
https://jira.spring.io/browse/DATAJPA-685
However, regardless of the enableDataTransactions parameter, if you add your own #Transactional annotation in your repository interfaces, it will be correctly applied.
However, however! If you specify #Transactional on the type level, the Spring framework itself (unrelated to data and JPA projects) will apply it only to methods declared in that type, not to the inherited methods. I find this behavior to be correct! Only by overriding the method, you can change its specification and implementation.
#Transactional(propagation=Propagation.MANDATORY)
public interface MyRepository extends CrudRepository<Something, Long> {
#Override
public Something findOne(Long id);
}
In this sample, MANDATORY propagation will apply to findOne, but it won't to findAll.
Note: Even though I find this behavior correct, I still don't like that there is no standard way to configure the MANDATORY propagation globally. In my opinion, it should even be default.
There were bugs with this in previous releases. I used Spring 4.2.2 and Sprint Data 1.11.0 to test it.
Bug reports:
https://jira.spring.io/browse/DATACMNS-715

Related

How do database connections get managed for Spring Data JPA repositories?

I have a question about how Spring Data repositories are handling the datasource connections. Assuming Spring Data repositories open and close the connection and the connection when the method executes, how does the transaction started by declaring #Transactional in my service layer span across multiple repository calls?
Who handles the database connections? The #Transactional annotation or the JPA repository?
tl;dr
Ultimately it's the Spring JPA / Transaction infrastructure managing the connection via the thead-bound management of EntityManager instances. The scope of the transaction is controlled by #Transactional annotations in the user code but ultimately defaulted in Spring Data JPA's repository implementation. Connection acquisition is performed eagerly in case an OpenEntityManagerInViewFilter is used (enabled by default in Spring Boot 1.x and 2.x).
Details
SimpleJpaRepository is equipped with Spring's #Transactional annotations so that it will make sure it runs transactions in cases JPA requires them (e.g. to execute a call to EntityManager.persist(…) or ….merge(…)). Their default configuration makes sure, they automatically take part in transactions started at higher levels of abstraction. I.e. if you have a Spring component that's #Transactional itself, repositories will simply participate in the already running transaction:
#Component
class MyService {
private final FirstRepository first;
private final SecondRepository second;
// Constructor omitted for brevity
#Transactional
void someMethod() {
… = first.save(…);
… = second.save(…);
}
}
Both repositories participate in the transaction and a failure in one of them will roll back the entire transaction.
To achieve that, the JpaTransactionManager will use the transaction management API exposed by JPA's EntityManager to start a transaction and acquire a connection for the lifetime of the EntityManager instance. See JpaTransactionManager.doBegin(…) for details.
The role of an OpenEntityManagerInViewFilter or –Interceptor
Unless explicitly deactivated, Spring Boot 1.x and 2.x web applications run with an OpenEntityManagerInViewFilter deployed. Its used to create an EntityManager and thus acquire a connection pretty early and keep it around until very late in the request processing, namely after the view has been rendered. This has the effect of JPA lazy-loading being available to the view rendering but keeps the connection open for longer than if it was only needed for the actual transactional work.
That topic is quite a controversial one as its a tricky balance between developer convenience (the ability to traverse object relations to loaded lazily in the view rendering phase) at the risk of exactly that triggering expensive additional queries and keeping the resources in use for a longer time.

Javers and MyBatis integration help needed

I'm having issues trying to get MyBatis and Javers (with Spring) integrated and working. I've followed instructions at http://javers.org/documentation/spring-integration/ and gotten the Aspect setup, and annotated my entity class and registered it with Javers, and the MyBatis interface correctly annotated with #Repository and #JaversAuditable on the appropriate methods, but still haven't gotten it to work, even setting breakpoints in the Javers Aspect, but nothing triggers.
I've also gone about it the other way, using MyBatis plugin interceptor, as per http://www.mybatis.org/mybatis-3/configuration.html#plugins (then used http://www.mybatis.org/spring/xref-test/org/mybatis/spring/ExecutorInterceptor.html as a basic example for commits). However while it's triggering, it's not doing what I expected and is basically just an aspect around on the commit method, which takes a boolean rather than containing which entity(ies) are being commited which would let me pass them to Javers. I suppose I could add an interceptor on the update/insert MyBatis methods, and then stored that in a ThreadLocal or similar so that when commit/rollback was called I could pass it to Javers as necessary, but that's messy.
I've got no clue where to go from here, unless someone can see something I've missed with one of those 2 methods.
So in my confusion, I realized that since MyBatis generates the concrete object for the Mapper Interfaces, Spring never seems the creation of that object, simply has the final object registered as a Bean in the context. Thus, Javers never has a chance to process the Bean as it's created in order to do any proxying or what not as necessary.
So, silly me. So I ended up creating a Spring-Data #Repository layer that mostly just passes the call through to the Mapper. Although on updates I'm doing some extra bits which the DAO shim layer (as I'm calling it) works well for.

Update database with JPA

I'm trying to update my (MySQL) database but it does'nt work.
Persistence code (called by a JSF managed bean):
#Override
public void changeEntrepriseStatut(int idEntreprise, int newStatut) {
Entreprise entr = em.find(Entreprise.class, idEntreprise);
em.persist(entr);
entr.setEntrepriseStatutInscription(newStatut);
em.merge(entr);
}
Ensure that you have an open transaction.
How you can do that does depend on how you manage your beans with jsf. There are at least four ways.
#ManagedBean - is the less power full possibility you should never do an operation which needs a transaction in there. (Call an EJB for example)
CDI beans - more powerfull but does also not have support for transactions build in when I am correct (not sure what the status of JavaEE7 is)
EJB - this is probably the easiest way, because of the support for #Transactional
Spring - never used that, if your using that please search the net for how to do that.
Additional never call em.persist on an already persisted bean. Just drop the line.

Play Framework - JPA - #Transactional error?

I'm experiencing a very strange behaviour with Transactions using play-2.2.2 with JPA and Eclipse-Link.
My Controller-Action is annotated with #Transactional like this:
#Transactional
public static Result submitOrder() {
// class does call private Methods which persist some entities (methods not annotated)
//...
Action is calling private methods to persist data (This should happen in the same transaction since no other Transaction is started).
During the Methods calls (at random locations) data gets written to db (inserts and updates). Debuging shows that the same (active) transaction is used before and after the write. EntityTransactionImpl:commit is never executed and transaction stays active until request is finished ( watched play.db.jpa.JPA.em().getTransaction() )
How is it possible that the data is written although transaction is still active?
It breakes the setRollbackOnly Mechanism since already written data isn't rolled back.
May there be any kind of Timeout that issue these writes.
Can you suggest any debug-entry-point to narrow down the problem (where can i start debuging the actual write-operations, if not in EntityTransactionImpl:commit)?
Dependencies in build.sbt
persistence.xml
The above described behaviour seemed very odd at first, but then i read about FlushMode and now it makes sense.
The FlushMode of eclipselink as well as hibernate is set to FlushModeType.AUTO
FlushModeType.AUTO automatically flushes Entities to the DB when it thinks it's neccessary. This can be because of an readable operation (Query) on a Persited (but not flushed) Entity but it also happened somehow randomly during my observations.
This breaks the rollback-on-failure mechanism, which I thought must be the standard behaviour of #Transactional.
To achive a propper rollback (on failure or if setRollbackOnly() is set), of all persisted but not flushed entities on transcaction commit, you have to explicitly set the FlushMode at the beginning of your Action.
JPA.em().setFlushMode(FlushModeType.COMMIT);
If you're using Eclipselink, you can also set the following property to make it default behaviour:
<property name="eclipselink.persistence-context.flush-mode" value="commit" />
Links which helped me understand:
Eclipselink Context Flushmode
what to use flush mode auto or commit
performance tuning hibernate

Lazy loading Spring Data JPA repositories

We have lots of repositories defined via the interface extends JpaRepository pattern. When running integration tests or certain entry points to our application, we only need a very small subset of those repositories.
Can we lazily load the actual repository implimentations?
Something equivalent to #Lazy on a #Bean? Note: I did at least attempt the naive solution of annotating the repository interface with #Lazy to no avail.
Even if it's a very old Question, I think some may still want to know about the use of #Lazy on Spring Data repositories :
it is actually supported since v1.5.0
Lazyloading will avoid to get all other dependency based on your main table or request. In your case you should set a limit / offset for that kind of operation.