Thursday, April 27, 2006

How to keep your hibernate POJO's clean from annotations

written by Marcel Panse

I've been reading a lot on blogs on the internet about annotations blurring your code in your java classes. Everybody states that you should be carefull about overly misusing annotations because it will easily blur your code. But if used correctly annotations will clean up your code and make stuff much easier to read. Using annotations instead of the hibernate mapping files (hbm.xml) gives a lot of benefits.
- You will have your POJO and mapping in one file which makes it more readable.
- Don't dont have to map basic properties one on one with your POJO's.
- Can't make typo's like when creating your hbm.xml and mispelled a package.
- Compile time validation.

Now how do i keep my POJO clean?

You should design your database 'hibernate style' to make the best use of annotations for your domain objects. With hibernate style i mean the following:
- Name tables exact the same name you use for your Class names. (like: Product)
- Name columns exact the same name you use for your properties. (like: productName)
- Name foreign keys like this 'propertyname_id'. (like: productGroup_id)

I follow with a simple exaple of a many-to-one case:





And here is the code:

Product.java

@Entity
class Product {
@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;

@NotNull private String name;
private String description;

@ManyToOne
@NotNull private ProductGroup productGroup;

//----getters and setters----//

public Integer getId() {
return this.id;
}

public void setId(Integer id){
this.id = id;
}

public String getName() {
return this.name;
}

public void setName(String name) {
this.name = name;
}

public String getDescription() {
return this.description;
}

public void setDescription(String description) {
this.description = description;
}

public String getProductGroup() {
return this.productGroup;
}

public void setProductGroup(ProductGroup productGroup) {
this.productGroup = productGroup;
}
}


ProductGroup.java

@Entity
class ProductGroup {
@Id @GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;

@NotNull private String name;

@OneToMany(mappedBy="productGroup")
private List products;

//----getters and setters----//

public Integer getId() {
return this.id;
}

public void setId(Integer id){
this.id = id;
}

public String getName() {
return this.name;
}

public void setName(String name) {
this.name = name;
}

public List getProducts() {
return this.products;
}

public void setProducts(List products) {
this.products = products;
}
}


Well, certainly easier then writing a hbm.xml mapping ain't it and much better to read...

This is a good example how to overdue your annotations: this blog. The thing is you don't need most of the properties. It is useless to declare a @PrimaryKey if you already have a @Id. You don't need an @Attribute if you have a @Basic, Hell you don't even need both of them because hibernate gets them by default. (btw if you need properties NOT mapped to your db then use the @Transient annotation).

In my example we even don't have to specify any package and class names because i've used a generic list (hibernate uses the generic for the class). We also don't have to specify the productGroup_id column because hibernate gets the _id by default.

Keep it clean, keep it simple

No comments: