Wednesday, March 25, 2009

More Hibernate glitches, part 2

I had previously written on an Expected positional parameter glitch in Hibernate when joining between entities using OneToOne and PrimaryKey + ForeignKey columns. It turns out, Hibernate has this problem no matter what field you query on the joined entity if you're quering by another entity. A way around this is to use the ID property of the joined entities and add another association to your HQL / Criteria query.

ie So if you have Person and Address having a OneToOne relationship


public class Person {
@OneToOne
private Address address;
}


... and you want to query for a Person by Address, you would probably write something like :

from Person p where p.address = ?


... in HQL. Well, this is where you start running into the Expected positional parameter glitch. Instead, write your query like this :

from Person p where p.address.id = ?


... and pass in a long / int / whatever type you use for an identifier for Person / Address instead and this will work around the glitch until it can be fixed.

Sunday, March 15, 2009

Stupid MySQL tricks

Recently, I found that our secondary server's MySQL partition was starting to get full. After running du -h --max-depth=1 several times recursively, I found that the source was the MySQL binary logs. As it turns out, MySQL comes with a very handy command for purging all log files. If you run :
show master logs
, you'll be given a list of the logs that the MySQL server is currently using. You can clear out old log files (some of which can be very large) by running the command
purge master logs to 'log-name-here -from-display'
. This will remove the old log files from the hard disk and save up some potentially much needed space.

Friday, March 13, 2009

Spring Webflow 2 Quirks

As I recently found out after a marathon debugging session, if you have a <transition> element that executes actions, and any beans involved in an expression evaluation don't exist in your application context, SWF2 will spin it's wheels instead of properly resolving things, leaving your flow in the lurch. At the time of this writing, I'm using Spring Webflow 2.

Thursday, March 12, 2009

More Hibernate glitches

I've recently discovered the joy of actually getting OneToOne primary key columns on objects working, so I've started using them more often (where appropriate). Naturally, increased use means increased chances of finding a bug, which I have. It seems there's a parser problem in HQL when it comes to querying on ID columns that are also objects. If you try to query on the object type (ie Person) rather than the ID type (ie Long), you'll get an exception saying something along the lines of :


Expected positional parameter count: 1, actual parameters: [Parent@bec357b] [from Child this where this.id.parent = ?]


The above line is from HHH-2254, but it's representative of the problem I ran across. The problem is that hibernate doesn't properly parse and fill in the parameters in the query. You can get around this by changing the query to use a simple type for ID instead of the object type.

Wednesday, March 11, 2009

Stupid Hibernate Tricks

I've recently been finding myself looking for a way to get Hibernate to override the default type for strings (varchar) and use char instead in order to boost performance of the database for fields that I know are going to have a fixed length. During my search, I came upon a couple of solutions.


Using annotations
You can use the 'columnDefinition' attribute of the @Column annotation to specify the SQL type directly. This has the unfortunate side effective of possibly reducing the database portability of your application.

Using SQL Dialects
You can override one of Hibernate's built in SQL Dialects and make char() types the default for strings. One other interesting possibility this opens up is that it allows you to only override the definition for certain lengths, ie, you could make any strings less than or equal to 4 characters in length use a char() definition, and the rest could use varchar definitions. This is done using the 'registerColumnType' method of Dialect.