The simplest example I can currently think of involves booleans and the lack of them in some databases like Oracle and MySQL (pre-5.0, that is). As it is right now, it's not uncommon to use a character-type column like Y/N or an integer-type column like 0/1 to mime a boolean in some databases.
As you may or may not know, in vanilla JPA you are unable to automatically convert this to a Boolean and thus you have some hideous Entity class like following:
@Entity
public class User {
@Id
private Integer id;
@Basic
private Character enabled;
// ... getters/setters
}
Now this is just awful... You most definitely want to treat the property enabled as a Boolean in your code, but JPA just doesn't provide any feature to map the Integer automatically to a Boolean.
However, there are two easy ways to solve this! If you don't care much about portability of your application and run JBoss and/or know that you will always use Hibernate as your persistence provider you can actually use Hibernate-specific annotations to use features which are not normally provided by JPA. One of these features is to use user-defined (or Hibernate built-in) type converters.
Consider following Entity class:
@Entity
public class User {
@Id
private Integer id;
@Basic
@org.hibernate.annotation.Type(type=“yes_no”)
private Boolean enabled;
// ... getters/setters
}
You can see that I added a Hibernate annotation and in this case I use Hibernate's pre-defined yes_no type. This will automatically map the character to a boolean.
This works equally well with other types, however, as I said: This is not always portable to another AppServer and if you choose this approach, you should use the complete package name to the unportable annotations so it's clearly visible that something is a little odd :)
If you want your application to be fully portable without having to be concerned whether Hibernate is used as a persistence provider on another AppServer you may want to use the "manual mapping" approach (at least I call it manual mapping and you will shortly see why), so check this out:
@Entity
public class User {
@Id
private Integer id;
@Basic
private Character enabled;
public Boolean getEnabled() {
if (enabled == null) return null;
return enabled == 'Y' ? Boolean.TRUE : Boolean.FALSE;
}
public void setEnabled(Boolean enabled) {
if (enabled == null) {
this.enabled = null;
} else {
this.enabled = enabled == true ? 'Y' : 'N';
}
}
}
This example is absolutely portable but you may end up clutter your entity classes with manual mappings in the getters and setters and before you realize you may want to use some sort of Utility class you might have duplicated a lot of code. Bummer!
As a final note I would just like to mentoin that the Hibernate annotation mentioned above is by far the only one you can use, you can check out the Hibernate Annotations API Javadoc to discover lot's of other features which make your JPA-experience more enjoyable and feature-rich.
1 comments:
Hi,
Great article, after reading your article, I decided to come out our own JPA Boolean data converter, an Java APT base compile time preProcess factory, which will automatically convert boolean field base on annotation's attribute. More info at my blog at here
Do share me your view..cheers!
Post a Comment