Programming with POJOs is emphatically a part and parcel of hibernate! But deciding the contents and the property access within the POJOs is at the discretion of the programmer. However, from a procedural programmer's perspective, the instant answer to such a scenario would be to opt for getters and setters for the properties within the POJOs! Before we have a look at whether this is really right and recommended, the other important consideration would be the accesstype! This can either be field or property level. Nonetheless, the controversies regarding the usage of Property or filed level access for the properties in the POJOs still continues and dosent seem to end even till date!
What is @Accesstype in Hibernate?
Let us say that you have a POJO as follows. The location of annotating the id property of the POJO with @Id and @column annotations in hibernate determines the access level of this domain object
public class Sample {
private int id;
private String title;
private String Description;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return Description;
}
public void setDescription(String description) {
Description = description;
}
}
Type 1: Field Access with @Accesstype in Hibernate
In the above POJO, if we annotate he id property as follows, then we are offering field level access to the properties inside the POJO. ORM framework chooses to access the fields using Introspection and reflection rather than via the getters and setters.
@Entity <br />public class Sample {<br /> @Id<br /> @Column(name = "id", nullable = false)<br /> private int id;<br /> <br /> @Column(name = "title", nullable = false)<br /> private String title;<br /> <br /> @Column(name = "description", nullable = false)<br /> private String Description;<br /> <br />}<br /><br />
In this case, getters and setters are not necessary! Such coding supports future changes to the structure of the domain object with ease. It not only offers clean/maintainable code but also better encapsulation, though a procedureal programmer would emphatically deny such a statement!And for those, who argue that having accessor methods offers better encapsulation, I would suggest to go through
this article for that would better explain the nuances very clearly!
In future, if there is a need for AOP integration or business logic incorporation within the domain objects, then that can be very well supported by adding the necessary behaviour to this POJO as and when needed!
Type 2: Property Access with @Accesstype in Hibernate
But, if we annotate the properties on top of the getter methods, then it is that the POJO uses property elvel access. It is as given below:
@Entity <br />public class Sample {<br /> private int id;<br /> private String title;<br /> private String Description;<br /> <br /> @Id<br /> @Column(name = "id", nullable = false)<br /> public int getId() {<br /> return id;<br /> }<br /> public void setId(int id) {<br /> this.id = id;<br /> }<br /> @Column(name = "title", nullable = false)<br /> public String getTitle() {<br /> return title;<br /> }<br /> public void setTitle(String title) {<br /> this.title = title;<br /> }<br /> @Column(name = "description", nullable = false)<br /> public String getDescription() {<br /> return Description;<br /> }<br /> public void setDescription(String description) {<br /> Description = description;<br /> }<br />}<br />
Such access of domain objects via getters/setters is again another way of accessing the properties of the POJO. The ORM framework uses accessors to set and get properties in this case. If in case, there is a need for business validations to be incorporated at a later date, then there might be a need for additional set of getters and setters that might have to be implemented in code. This not only makes the coding cluttered but also makes the maintenance burdensome!
Mix up!
This is always possible! You can have the default field access and mark the properties that need the proeprty level access as transient. Further, you can define the annotation for such properties before their accessors
@Entity <br />public class Sample {<br /> @Id<br /> @Column(name = "id", nullable = false)<br /> private int id;<br /> @Transient <br /> private String title;<br /> @Transient <br /> private String Description;<br /> <br /> <br /> @Column(name = "title", nullable = false)<br /> public String getTitle() {<br /> return title;<br /> }<br /> public void setTitle(String title) {<br /> this.title = title;<br /> }<br /> @Column(name = "description", nullable = false)<br /> public String getDescription() {<br /> return Description;<br /> }<br /> public void setDescription(String description) {<br /> Description = description;<br /> }<br />}<br />
Existing Controversies
With respect to performance, it can be vouched that there is not much of difference between the two methods discussed above. However, While a
survey by google vouches that the field access is preferred, there is still another face to this issue that needs to be analysed in depth!
As per the @AccessType implementation of hibernate, if we intend to get the identifier of an associated object in hibernate, if we use property level access, then hibernate understands that there is getId() method in the corresponding POJO and hence gets the id without initializing the proxy. However, this does not work if we use filed level access. If we intend to get the id of the associated object, since there is property level access defined, hibernate does not knoww about the accessor methods in this domain object and hence tries to initilaize the proxy to get the id of the associated object!As a result,
Hibernate team strongly suggests the use of property access if we do not want the proxy initialization to happen since that might result in lazy initialization exception if done out side the session.
Yet another temporary solution has been discussed in
this link. However, a note with title @org.hibernate.annotations.AccessType in
hibernate documentation
The annotation @org.hibernate.annotations.AccessType should be considered deprecated for FIELD and PROPERTY access. It is still useful however if you need to use a custom access type.
Adding fuel to this fire is the
bug reported in hibernate. While this points to the proxy initialization issue on calling getId() of an embedded object within hibernate, it is very clear that Property level access is being discouraged by Hibernate (though Spring's dictum is to opt for field level access only as in
this link.
Best Practices
- There is not much of difference between the field and property level access with respect to performance.
- Field level access would be preferred if the code avoids hibernate proxy pitfalls!If there is a need for property access later, this can always be supported by adding the necessary accessors!
- Field level access proves to be good if you really want the annotations closer to the code. This not only gives a fare idea of the property details but also avoids unnecessary accessors that might prove to be great evil. Additionally, having accessors is emphatically not a good OO design strategy!
- If you are using filed level access, remember that Hibernate would initialize the proxy on getting the id of an associated object at least until the bug gets resolved.
- Property level access can be implemented as long as you do not have business logic or validations within your domain objects since one such scenario can prove to be very dangerous! The positive aspect about this type of access is that Hibernate does not initialize the proxy in case of getting the identifier of the associated POJO.
- Overall, the usage of field and property level access depends much on the requirement as the first consideration and then the coding style!
If you find the information pretty pretty helpful, I would really be happy if you would keep me posted! If you had wanted some other information related to the same topic, I would suggest you to drop a note to me using the comments form for that would help me in getting back to you with the details you are in need of!