Categories
Coding

Hibernate Criteria Queries, Part 2

Another strange issue with Hibernate Criteria queries…

Say you have a class Foo which has a one-to-one property mapping to a class to type Bar. The class Bar is a custom UserType implementation. The mapping might look as follows:

<property name="bar" type="uk.co.researchkitchen.usertype.Bar" column="bar" />

Now say you want to include this property in a Criteria query. Specifically, you want to query the property called name of the Bar class. As per the last pot I wrote about this, it seems logical that you would create a sub-criteria for the Bar property, and add an Expression on Bar.name, like so:


Criteria barCriteria = fooCriteria.createCriteria("bar");
barCriteria.add(Expression.eq("name""TestName"));

However, this doesn’t work. Hibernate theows a QueryException with the message “not an association type”. Stepping through the code, this happens when Hibernate internally creates an instance of a CustomType class to represent the UserType property that we are querying. Hibernate checks if the class is a composite or association type (of which CustomType is neither), and throws an Exception if it isn’t. However, you can get this to work by using the Example functionality of the Criteria class, as follows:


Foo foo = new Foo();
Bar barType = Bar.getInstance();
foo.setBar(barType);
hibCriteria.add(Example.create(foo));

Quite why this works and the former method doesn’t, I don’t know. I haven’t had time to look at it in detail. At least for now, there is a (slightly non-intuitive) workaround.

Categories
Coding

The Joy of Subversion

I had a bit of spare time this weekend, so I revisited a project that I occasionally work on – the Jakarta Commons::Net project. From time to time, if my schedule permits (rarely these days, sadly), I’ll visit Bugzilla and try to fix some bugs. This time however, I had a feature to add – I needed support for a parser for a Novell Netware FTP server (truly a rarity these days, however the business school I am currently studying at uses it), and decided to add it. So after a couple of hours, I had a working parser implementation and corresponding unit tests.

Most of Apache these days has migrated from CVS to SVN, and the general comfort level as regards to SVN seems to have increased considerably. I decided to upgrade my (extremely) out-of-date copy of TortoiseSVN while I was checking in the changes. I was struck by a few things:

  • TortoiseSVN (and Subversion, more generally) has come a long way. The menu has expanded quite a bit since I last used it, and there are a ton of new features in there. No doubt there are plenty of low-level enhancements that have been incorporated as a result of new versions of Joe Orton’s excellent Neon library, but there are also some more fundamental changes in there.
  • Subversion, like CVS, follows the 80/20 rule – the 80% of operations that you will perform repeatedly are very intuitive and easy. This means that some more complex operations can be more fiddly, but most of the time, you don’t notice, because you don’t need them. I contrast this with ClearCase, which I am using at the moment on a separate project, and the difference is pretty stark. Where SVN is elegant, ClearCase is clunky, and where SVN is intuitive, ClearCase is confusing. Of course, ClearCase in its own right is very, very powerful, but it looks and feels like a 20-80% type of product.
  • I used to have the odd “lock up” with SVN’s Berkeley DB storage engine (especially if a commit in progress got interrupted), which doesn’t seem to happen any more. The CVS-alike file system backend looks like it will probably be the way forward.
  • There were traditionally some doubts about the scalability of SVN, but it hosts some pretty big repositories now.
  • The merging/branching process is quite straightforward under SVN. TortoiseSVN even gives you the ability to do a “dry run” of the merge process before actually risking anything – very cool.

    Tortoise Merge dialog

There are a couple of things that I’m not 100% happy with, and one is that SVN can’t seem to efficiently figure out how to retrieve a list of revisions for a particular file, so when you try to retrieve a revision graph for a specific file, it seems to want to traverse the revision tree for the entire repository. This results in TortoiseSVN telling you that it will take 5 hours to generate a revision graph! I guess this is the same issue that prevented a port of CVSGraph from happening. Hopefully they’ll sort this out.

Categories
Coding

Hibernate Criteria and Composite Properties

Criteria queries are enormously useful feature in Hibernate, as they allow you to dynamically build up a complex query. They are very useful, for instance, when you have a search form UI (or a set of search forms) and you want to build up a search query from any combination of the search parameters contained in the form. However, there is one feature regarding Criteria queries which is non-obvious – you need to create a sub-Criteria for each composite property that you wish to map. For instance, the code below will not work:

Criteria hibCriteria = getDao().createCriteria(Event.class);
hibCriteria.add(Expression.like("title", name));
hibCriteria.add(Expression.ge("calendar.startDate", startDate);
hibCriteria.add(Expression.le("calendar.endDate", endDate);

If you want to reference a nested property in a Criteria query, you need to create a separate Criteria instance for each property:

Criteria hibCriteria = getDao().createCriteria(Event.class);
hibCriteria.add(Expression.like("title", name));

// Add a sub-criteria for the nested property set
Criteria calCriteria = hibCriteria.createCriteria("calendar");
calCriteria.add(Expression.ge("startDate", startDate);
calCriteria.add(Expression.le("endDate", endDate);