In the spring documentation regarding testing, it states:
Avoid false positives when testing ORM code
When you test code involving an ORM framework such as JPA or Hibernate, flush the underlying session within test methods which update the state of the session. Failing to flush the ORM framework's underlying session can produce false positives: your test may pass, but the same code throws an exception in a live, production environment. In the following Hibernate-based example test case, one method demonstrates a false positive and the other method correctly exposes the results of flushing the session.
Can someone explain why i need to call flush?
Spring documentation uses the wrong concept. It has been clear
Here goes wikipedia
If you see the sample provided by Spring, The production environment throws an exception (A GenericJDBCException), but it has not been detected. In order to see, you must call the underlying commit when using some ORM provider.
XUnit Test patterns definition
So the right concept is falseNegative
Well, you actually skipped the interesting part, the example :) Here it is:
What this example tries to illustrate is that unless you actually
flush
the session (A.K.A. the first level cache) to sync in-memory changes with the database, you're not really testing the database integration and might not test the real expected behavior or miss a problem.For example, the database could return an error because of, say a constraint violation, and if you don't hit the database, you won't exhibit this right behavior, as in the
falsePositive()
test method above. This test method should fail, or expect an exception but will just pass. On the other hand, the other test method with the flush does test the real behavior. Hence the need toflush
.Annotating Spring tests with @Transactional is convenient but it's not how your production code will be executed. The @Transactional annotation will start a transaction prior to running your test method and it will roll it back when the test method finishes.
While commit is preceded by a flush, the roll-back is not, so a manual flush is a safety-mechanism to ensure all Entity changes are translated to SQL statements.
A more appropriate design would be to draw the transaction boundaries explicitly like this:
The TransactionTemplate will commit your code so there's no need for manual flushes.
If you call @Transactional service methods through their interface, you won't need the transactionTemplate at all, since you are calling a Spring proxy which will call TransactionInterceptor (assuming you instructed Spring to be aware of transaction annotations: ) and therefore transactions will be started/committed on your behalf.
Does anyone checked with the annotation @TransactionConfiguration? If you are using @Transactional annotation driven in your project, you can simply set @TransactionConfiguration(defaultRollback = false, transactionManager = "YourTransactionManager") in your test case will work perfectly, hopefully this will helps you.