In all of these scenarios, the task is to teach Hibernate a new way to translate between a particular kind of in-memory value and its persistent database representation.
Hibernate lets you provide your own logic for mapping values in situations that need it, by implementing one of two interfaces: net.sf.hibernate.UserType or net.sf.hibernate.CompositeUserType.
It's important to realize that what is being created is a translator for a particular kind of value, not a new kind of value that knows how to persist itself. In other words, in our ZIP code example, it's not the ZIP code property that would implement UserType. Instead, we'd create a new class implementing UserType, and in our mapping document specify this class as the Java type used to map the ZIP code property. Because of this, I think the terminology of "user types" is a little confusing.
Let's look at a concrete example. In Chapter 6 we saw how to use Hibernate's built-in enumeration support to persist a typesafe enumeration to an integer column, and we had to work around the fact that many object-oriented enumerations have no natural integer representation. While we can hope that Java 1.5 will allow Hibernate to resolve this tension in a universal way, we don't have to wait for that to happen, nor do we necessarily have to make the kind of compromises we did in Example 6-2. We can define our own custom value type that persists the SourceMedia class on its own terms. Later in the chapter we'll look ...