Debugging JUnit Tests in a Hibernate driven Spring Application - java

Maybe this has been answered already, but i did not find any suggestions out there...
My Project is a Spring Utility Project, the database i use is MySQL and for persistence i´m using Hibernate in combination with c3p0 connection pooling. i´m on spring 3.2 and hibernate 3.5.
So here is what i want to do:
I want to debug a JUnit test, step over some persistence functions (save, update, etc. ) and then check the entries manually in the database via SQL. Because of the JUnit tests always running in a transaction, i cannot check the entries in the database, because a rollback happens every time a test finished / a commit never occurs.
Is there a way to fake transaction existence, or bypassing them during JUnit tests?

Perhaps you can flush the transaction in Hibernate during your debugging session and force Spring/Hibernate to write to the database.
Or you can turn off transactions for your debugging session.

Rather than fake transaction existence, the best approach to looking at the database while the transaction is taking place is to query with an isolation level that allows dirty reads. The mechanism for doing this varies from database to database, and in MySQL you can use
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
prior to querying.
Clearly you will also need to force Hibernate to flush writes to the database during your test, and set your breakpoint after the flush.

Related

How does Hibernate Envers work?

I am using Hibernate envers in one of my projects. It works really good and does that job.
I am trying to understand the internal working mechanism of envers.
How does envers work internally?
What happens when the actual transaction is succeeded and the audit table update fails? Will the entire transaction be rolled back?
Does envers be executed in a different thread than the actual one serving the request? or can it be?
Hibernate Envers provides a very simple solution for CDC (Change Data Capture).
It uses the Hibernate Event system to intercept all entity state transitions and audit them.
The database transaction will roll back and both the actual changes and the audit log is rolled back.
No. Envers is a synchronous audit logging mechanism. For asynchronous audit logging, you need to use Debezium.
If you want to use Envers, make sure you are using the validity audit strategy because it performs better than the default one.

How to remove non-transactional database logging after running integration tests?

I'm working on a Java/Spring app that requires audit logs to be written to a database. All services are currently marked as #Transactional - so if there is a failure, the changes are rolled back.
But audit logging is the exception to this - it should always succeed - so have been considering marking the AuditLogService as either Propagation.NOT_SUPPORTED or Propagation.REQUIRES_NEW.
The question is how to craft the integration tests. Ideally these should not leave log entries in the database. Would prefer not to have to manually delete this at the end of the test. Is there perhaps a way of marking a test as transactional that would include all transactions including ones that have started via Propagation.REQUIRES_NEW?
I ended up doing exactly what I said I didn't want to do and deleting all the operational data at the end of each test. (This actually worked better as the tests were no longer run in an overarching transaction, which masked some bugs, e.g. relating to Hibernate lazy loading.)

Rollback changes in test after manual interaction with the datasource?

I'm using dbsetup for my db tests. The problem is I can't manage to get data rolled back after each test using the aproach which have always worked which is annotating the test case (or method) with #Transactional annotation. I suppose this happens because dbsetup uses the DataSource itself so Spring can't get track of what's being done to the database. How to make this work?
DbSetup is not tight to Spring in any way. It gets a JDBC connection from a DataSource and commits it when it's done.
The recommended way of using DbSetup is to clear and populate the tables before each test. Using a DbSetupTracker allows avoiding useless repopulations in case a test uses the same data as a previous test, and this previous test hasn't altered the data. This is described in the user guide.

Exception if no transactions are configured?

I am using spring/hibernate stand alone application. if i dont configure Transactions i am getting below excpetion.
Exception in thread "Thread-1" org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
in spring/hibernate integrated application is it mandatory to have transaction configuration?
Thanks!
Basically, yes. The Hibernate documentation says:
Database, or system, transaction boundaries are always necessary. No
communication with the database can occur outside of a database
transaction (this seems to confuse many developers who are used to the
auto-commit mode). Always use clear transaction boundaries, even for
read-only operations. Depending on your isolation level and database
capabilities this might not be required, but there is no downside if
you always demarcate transactions explicitly. Certainly, a single
database transaction is going to perform better than many small
transactions, even for reading data.

Hibernate transaction problem

When I execute some queries inside Hibernate transaction -> the data successfully updated in my mysql, but in my application there are still old values. When i restart - it`s Ok. If i set autocommit mode - works fine, but i have to use transaction ;-). Any ideas?
Thanks in advance.
Manipulating the database directly with UPDATE doesn't affect the objects cached in the session. You should clear the session (Session.clear()). Something like:
session.flush()
session.clear()
query.executeUpdate()
Or even better, you can avoid the problem by not using update queries and manipulating the object state in memory:
myobj.setName(newValue)
session.saveOrUpdate(myobj)
In hibernate either you are using JPA API or Hibernate's native API any query that you run using below interface
Criteria (Hibernate Native API)
Query (Hibernate Native API)
EntityManager createQuery() (JPA)
The queries dont interact with the second level or first level cache . They directly hit the database .If your query is updating the entities currently in the persistence context , those entities will not reflect the changes.This is the default behavior.
In order to update your context to show the latest state of entity use the refresh() in Session or in EntityManager to reflect the latest entity state in persistence context.
Read the docs below for more info
http://docs.oracle.com/javaee/7/api/javax/persistence/EntityManager.html#refresh-java.lang.Object-
https://docs.jboss.org/hibernate/orm/3.5/javadocs/org/hibernate/Session.html#refresh%28java.lang.Object%29
Otherwise as a convention always run your DML before loading any data in the persistence context.
Hope this helps :D

Categories

Resources