I have a Java application that uses Hibernate 4.3, c3po db pooling and H2 1.3.172 database. using a profiler Ive realized that although it is multithreaded when I use more cpus it doesn’t get much faster because the threads are spending alot of time being blocked by other threads with them both trying to do things with Hibernate.
-
I am not clear if this is because hibernate is locking tables or if it is simply that the cpu is maxed out. If it is locking I am a little confused since all my hibernate tables have a @Version annotation so I thought this would do optimistic locking. There are not many tables so the threads could be accessing the same tables however the threads blocking each other should not be accessing the same same rows. The only database related thread that seemed to be busy was H2 Log Writer DATABASE, does everything go through this, the 10 C3PO Pool Helper threads did not appear to be, I couldnt see Hibernate specific threads.
-
The application works on music files, and can process many folders at once. When the task starts it starts loading folders as specified by user, the first time a folder of songs is loaded the music files metadata is stored as a SongFile entity, subsequent runs of the tasks can retrieve the metadata directly from SongFile entities in the database without going to filesystem. However The application has a main set of tables that persist, and a couple of tables that just represent the results of a task, each time the task is run out these temporary tables are emptied (using truncate). So as each folder is loaded a copy of each SongFile is made to a Song entity and this is a key cause of the block.
-
I was previously saving each song with save in its own session, I now use a single session for all songs in the folder and I am using persist instead but it hasn’t made any difference, and I’m not clear if data is written to database when you call persist or just when you cal commit ?
public static void createSongsFromSongFilesInOwnSession(List<SongFile> songFiles)
{
Session session=null;
try
{
session = HibernateUtil.beginTransaction();
for (SongFile songFile : songFiles)
{
Song song = new Song();
copySongFileToSong(song, songFile);
session.persist(song);
}
session.getTransaction().commit();
}
finally
{
HibernateUtil.closeSession(session);
}
}
- Could I/Should I create using SQL instead, I thought about this but I was put off because I wasn’t clear how to deal with @Version field