programmatically set show_sql without recreating SessionFactory? - nhibernate

In NHibernate, I have show_sql turned on for running unit tests. Each of my unit tests clears the database and refills it, and this results in lots of sql queries that I don't want NHibernate to output.
Is it possible to control show_sql without destroying the SessionFactory? If possible, I'd like to turn it off when running setup for a test, then turn it on again when the body of the test starts to run.
Is this possible?

The only place you can set this is when building a NHibernate.Cfg.Configuration.
Once you've created a SessionFactory from your Configuration, there's no way to access the configuration settings, which I think is one of the reasons for using a factory pattern: to ensure that instances once successfully built can't be messed up by runtime re- or mis-configuration.
If you really need that feature, get the NH source code and find the place where the show_sql setting is evaluated.

Another option although it may/may not be as good is to use NHProf and just initialise NHProf when testing.
NHProf doesn't log setting/clearing database just queries used.

Related

Environment specific migrations cause issues with copying a database to different environments

We've made use of environment specific migrations for things like seeding data, data correction, applying table grants. There are times when we'd like to take a copy of production, for example, and import it to another lower environment, either as a periodic refresh, or to start a new test environment. However, as expected, we end up with various failures like Detected applied migration not resolved locally and Detected resolved migration not applied to database. I see there are various flags (ignoreIgnoredMigrations, ignoreMissingMigrations and outOfOrder) to allow us to bypass these issues.
Are there best practices for handling scenarios like I described? Is there a way to run an environment specific migration that doesn't file an entry in the flyway_schema_history table? Other approaches to this issue that I haven't mentioned?
Thanks in advance for any insights.
We have used ignoreMissingMigrations as one approach around this issue.

Clearing Locks between JUnit tests in Hibernate Search 4.1

we recently upgraded to Hibernate Search 4.1 and are getting errors when we run our JUnit tests based on the changes hibernate made with regards to locks. When we run Junit tests with the AbstractTransactionalJUnit4SpringContextTests we often see locks left after each test. In reviewing (How to handle Hibernate-Search index recovery) we tried the native locks, but this did not resolve the issue.
We've tried out the various locking mechanisms (simple, single, and native) using the default directory provider (Filestore) and regularly see messages like:
build 20-Apr-2012 07:07:53 ERROR 2012-04-20 07:07:53,290 154053 (LogErrorHandler.java:83) org.hibernate.search.exception.impl.LogErrorHandler - HSEARCH000058: HSEARCH000117: IOException on the IndexWriter
build 20-Apr-2012 07:07:53 org.apache.lucene.store.LockObtainFailedException: Lock obtain timed out: NativeFSLock#target/indexes/Resource/write.lock
build 20-Apr-2012 07:07:53 at org.apache.lucene.store.Lock.obtain(Lock.java:84)
build 20-Apr-2012 07:07:53 at org.apache.lucene.index.IndexWriter.<init>(IndexWriter.java:1108)
or
build 19-Apr-2012 19:31:09 ERROR 2012-04-19 19:31:09,395 153552 (LuceneBackendTaskStreamer.java:61) org.hibernate.search.backend.impl.lucene.LuceneBackendTaskStreamer - HSEARCH000072: Couldn't open the IndexWriter because of previous error: operation skipped, index ouf of sync!
Some of these messages seem to show the lock issue cascading from one test to another, hence the need for the reset, and some may be valid because the tests are testing 'invalid' behaviors and how our application reacts to them, but often because of cases like this where the ID is null
build 19-Apr-2012 19:31:11 Primary Failure:
build 19-Apr-2012 19:31:11 Entity org.tdar.core.bean.resource.CodingSheet Id null Work Type org.hibernate.search.backend.PurgeAllLuceneWork
But, regardless, we need to make sure that one test does not effect another.
In reading some of the discussions (email discussion on directory providers) it was suggested that the RAM based directory provider might be a better option, but we'd prefer to use the same provider as we use in production wherever possible.
How should we be resetting HibernateSearch between tests to clean up lock files and reset potential issues where the index is out-of-sync or corrupted? At the beginning of the test suite, we wipe the index directory, is it recommended to wipe it after every test?
thanks
If you have stale locks in the directory, it means that Hibernate Search wasn't shut down properly as it certainly will close the locks.
If you start a new Hibernate SessionFactory in each test, you should make sure it's closed as well after the test was run:
org.hibernate.SessionFactory.close()
(This is often missing in many examples as there are no noticeable problems when forgetting to close a Hibernate SessionFactory, but has never been optional and might leak connections or threads).
The thread from the Hibernate mailing list you linked to ended up changing the locks to use native handles in Hibernate Search 4.1, so that locks are cleaned up automatically in case the JVM crashes or is killed. But in your case I guess you're not killing the VM between tests, so you just need to make sure locks are released properly by shutting down the service.
exclusive_index_use=false hides the problem as the IndexWriter will be closed at the end of each transaction. That makes it slower though, as it's significantly more efficient to reuse the IndexWriter. The reason you have this issue after upgrading to Hibernate Search 4.1 is that this option was changed to true by default. But even then, you should still close it properly.
My understanding is that Spring manages the SessionFactory lifecycle, so it is not necessary to call close() at any time.
I have seen this locking error when there are multiple contexts loaded during a test run. For example, the first context creates the locks on the index file. The second context attempt to access the same indexes and fails due to the existence of the open SessionFactory from the first context.
I have fixed this by using #DirtiesContext which closes context before the next is instantiated

Mapping for component xxx not found in ORM app

I'm doing some TDD with a ColdFusion ORM application so I'm letting the application.cfc in my tests directory so I'm setting dbcreate="update" so the tests will create the database tables. Every time I change a model's method and re-run my tests I get the following error:
Mapping for component models.user.User not found.
If I restart the server the error goes away, however this is a terrible workflow so I'm looking for a better way to fix this problem.
have you tried dbcreate=dropcreate?
From my experience, update or dropcreate might fail for the first time, but if you ormreload again, it might just work.

Nhibernate Profiler - Shows no information other than "session"?

So I am having problems getting NHibernate intergated in my MVC project. I therefore, installed the NHProfiler and initialized it in the Global.asax.cs file (NhibernateProfiler.Initialize();).
However, all I can see in the NHProf is a Session # and the time it took to come up. But selecting it or any other operations doesn't show me any information about the connection to the database or any information at all in any of the other windows such as:
- Statements, Entities, Session Usage
The Session Factory Statistics only shows Start time, execution time, and thats it.
Any thoughts.
Do you have any custom log4net configuration? Just thinking that might be overwriting NHProf's log4net listener after startup. If you refresh the page (and hence start another session*), does NHProf display another Session start? Also verify that your HibernatingRhinos.Profiler.Appender.dll (or HibernatingRhinos.Profiler.Appender.v4.0.dll if you're using .NET 4) is the same one as the current version of NHProf.
* I'm assuming that you're using Session-per-Request since this is a web app.

How do I delete all JPA entities?

In my testing code I need to have a blank/empty database at each method. Is there code that would achieve that, to call in the #Before of the test?
Actually you always can use JPQL,
em
.createQuery("DELETE FROM MyEntity m")
.executeUpdate()
;
But note, there is no grants that entity cache would be cleaned also. But for unit-test purposes it is look like good solution.
In my testing code I need to have a blank/empty database at each method.
I would run the test methods insider a transaction (and rollback at the end of each method). That's the usual approach. I don't see the point of committing a transaction and writing data to the database if you DELETE them just after. Just don't commit.
An alternative (not exclusive) would be to use DbUnit to put your database in a known state before a test execution. When doing this, you usually don't need to clean it up.
Another option would be to use raw JDBC to drop the database if exists and then have JPA recreate the whole database. Will be pretty slow though.