Apr 27, 2010

Field versus Property Access in Hibernate :Understanding @AccessType in Hibernate

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

  1. There is not much of difference between the field and property level access with respect to performance.
  2. 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!
  3. 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!
  4. 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.
  5. 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.
  6. 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!

16 comments:

  1. HI..nice post...It gave a whole idea for my issue..
    Can this thing be done from XML Mapping file itself?
    I am not using Annotations but I don't want Hibernate to call getter/setter for the property access. Can I give access to hibernate to directly use my fields?This is to be done from XML file...
    Thanks in advance

    ReplyDelete
  2. Yes, you can give that from the xml mapping. The tag has an attribute that can be set for the access type. The default of this attribute is property.

    Please see the code snippet below: Here you can specify the access as field and have field access for that entity! Hope this answers your question!

    ReplyDelete
  3. <hibernate-mapping
    schema="schemaName"
    catalog="catalogName"
    default-cascade="cascade_style"
    default-access="field|property|ClassName"
    default-lazy="true|false"
    auto-import="true|false"
    package="package.name"
    />

    ReplyDelete
  4. @Leon

    Thanks for the comment! Would appreciate if you could drop in your feedback on the articles posted here whenever you happen to go through any of them! thanks again!

    ReplyDelete
  5. I found your post by googling "hibernate mapping properties vs setters"
    Now, I realize the complexity of the problem described, I'm sure you saved me hours of investigations!
    Thanks.

    ReplyDelete
  6. @Anonymous

    Thanks for your feedback!! Do keep us posted with your invaluable comments whenever you read the articles here for that would help me in offering more productive and useful articles there after!

    ReplyDelete
  7. Cool nice material, until i read this i did not understand the purpose of using annotations at certain level. Thank you very much.

    ReplyDelete
  8. It is really very nice to hear that this article helped you to understand the intricacies! Would be updating the site with more articles and see you then! Thanks for your valuable feedback!

    ReplyDelete
  9. Hi, In case of field level access type, how do you get the value of the fields in DAO classes? Or for that matter, how do you set values to persist in the Database?

    ReplyDelete
  10. Very clear explanation and assessment! Thanks! ..could use a spell-check though :)

    ReplyDelete
  11. Yes. I will surely use spell check hereafter! Sorry for that! Thanks for your feedback

    ReplyDelete
  12. @Ondrej Medek

    Should I create a user id there to vote for the bug? Let me know

    ReplyDelete