Hibernate version:
3.0.5
Name and version of the database you are using:
PostGres 8 / Oracle 10g
We have been discussing different ways to ensure type-safety for uuid-based ids when accessing Hibernate-persisted objects through an EJB session bean.
Our application is supposed to be full-blown J2EE, so we have created a number of DTO-classes that are the "serializable representation" of our persistent classes. Client applications utilize the persistent classes through their DTO-representation. For now, we have implemented our EJB-interfaces as simple as possible, using java.lang.String for all id-based queries:
Code:
public interface SearchFacade {
public RevisionDTO retrieveRevision(String id);
}
The problem with this approach, is that erroneous use of this code (e.g. clients passing something else than a UUID with the id argument), can only be detected runtime. Such erroneous use could however to some extent be detected compile time, by using some sort of UUID-type (instead of String) for the id argument.
A step in the right direction could hence be to make a custom UUID-class (we use Java 1.4, so we unfortunantelly don't have the java.util.UUID class available at this time). Our UUID class could look something like this:
Code:
public class UUID implements Serializable {
String value;
}
Pretty simple stuff, but at least it will make client programmers aware that they are supposed to send a UUID.
We however don't see this solution as completelly satisfactory: We also want to make sure that the UUID that is passed is a UUID for the particular type of object being sought. For instance, when retrieving Revision-objects, so we want to make a RevisionUUID class:
Code:
public class RevisionUUID extends UUID {
}
Our EJB interface would then change to:
Code:
public interface SearchFacade {
public RevisionDTO retrieveRevision(RevisionUUID id);
}
We however have some unresolved problems with this approach:
-How do we actually implement the UUID-generation? A straight-forward approach would be to make the id-column in the database longer than 32 characthers and append a value to the UUID generated by Hibernate. The appended value indicates which type the saved object has. E.g. "eb529fec649811d7b236000629ba5445.REVISION". When clients invoke the retrieveRevision() method, we could check to see if the value of the RevisionUUID-argument ends with "REVISION".
If we are to accomplish this, it seems like we need to override the org.hibernate.id.UUIDHexGenerator of Hibernate, and make sure it appends something that identifies the type of the object being stored. In that case: How to we define this to be the generator class in the mapping file? Is this at all possible, without modifying the Hibernate code directly? In other words, is it possible to write something like this:
Code:
<id name="oid" type="java.lang.String" unsaved-value="null">
<column name="OID" not-null="true" length="64"/>
<generator class="my.custom.uuid.hex" />
</id>
-Are there other ways to do this, that is, maintain type safety when quering for objects using their IDs/primary keys?
All of this might seem like overkill (and maybe it is), but as we are developing an API for client programmers, and our database model is fairly complex, we want to limit as many potential errors as possible.
We would be most interested to hear any comments to our proposed approach.