Our series on Hibernate continues with the addition of a Hibernate collection. The collection is a basic building block in programming and storing Keyword objects inside a KeySet collection object gives us an easy way to query and display our persistent objects.
The first step in implementing our KeySet class is deciding whether there will be a one-to-many or a many-to-many relationship between KeySet and Keyword objects. A Keyword object may not be contained in multiple KeySet objects in a one-to-many relationship and it may be contained in multiple KeySet objects in a many-to-many relationship.
This example will use a many-to-many relationship. This requires a new table with two foreign keys tying KeySets and Keywords rows together – a one-to-many relationship would require a foreign key in the Keywords table that referenced the KeySets table. The KeySet.hbm.xml file follows (comments show the SQL used to create the respective tables). It is quite similar to the Keyword.hbm.xml file with the addition of the set tag.
1 | <hibernate-mapping> |
We will skip the KeySet.java class as it is primarily boilerplate get/set methods and is quite similar to the Keyword.java class. However, please note that there are some changes to our Keyword implementation:
- The parameter definition unsaved-value=”-1” has been added to Keyword.hbm.xml to explicitly declare an unsaved id value. And the static final int unsaved_value = -1 has been added to the Keyword java file and is used to set the initial value of the id member value. The two values need to match and should correspond to an invalid id value.
- The default constructor and the setId function are now protected. Hibernate sets the id when an object is loaded or saved and everything else should leave it alone.
- A toString() method has been added for easy output.
In addition, the build.xml file has been modified to add a DEBUG property that defines the value of the debug attribute of the javac task. The DEBUG property is set to true and Java source is now compiled with debug information.
Now let’s take a look at some code to load, query and create persistent objects. First, don’t forget to add the class to the configuration object. The error message “net.sf.hibernate.QueryException: unexpected token: as [from KeySet as ks …]” can be a bit perplexing until you’ve encountered it a few times.
1 | Configuration cfg = new Configuration(); |
Second, let’s query for a KeySet object.
1 | tx = session.beginTransaction(); |
If we find the KeySet we’re looking for, then we print it. Otherwise, we create a KeySet object, populate it with two Keyword objects and persist all three objects.
1 | if ( ! existing.isEmpty() ) { |
Now, start with a clean database and execute twice:
1 | $ ant run Buildfile: build.xml init: compile: clean-run: setup-run: run: [java] Create {0:colors|[1:blue, 0:red]} BUILD SUCCESSFUL Total time: 14 seconds $ ant run Buildfile: build.xml init: compile: clean-run: [delete] Deleting: /Projects/Learn/Hibernate/Simple/hibernate.log setup-run: run: [java] Read {0:colors|[0:red, 1:blue]} BUILD SUCCESSFUL Total time: 13 seconds |
Success, we’ve stopped adding persistent objects to the database with every execution. And we’ve stored and retrieved objects. You can download the source for this simple Hibernate collection. As a reminder, here is my hibernate software configuration.
Disclaimer: I don’t claim to be an expert on hibernate. Please send comments and corrections.