Vincent Partington has more than 10 years of enterprise Java experience. He has written and presented on topics as diverse as performance, security, RIA, and persistence technologies. Vincent Partington is the Chief Technical Officer of XebiaLabs where he is responsible for their flagship deployment automation product Deployit. Vincent is a DZone MVB and is not an employee of DZone and has posted 25 posts at DZone. You can read more from them at their website. View Full User Profile

JPA Implementation Patterns: Field Access vs. Property Access

09.09.2009
| 31326 views |
  • submit to reddit
I will continue the JPA implementation patterns series by discussing the relative merits of field access vs. property access.

The JPA specification allows two ways for the persistence provider to access the persistent state of an entity. The persistence provider can either invoke JavaBeans style property accessors (getters and setters) or access the instance fields of the entity directly. Which method is used depends on whether you have annotated the properties or the fields of an entity.

The JPA 1.0 specification does not allow you to mix access types within an entity or even an entity hierarchy. If you have annotated both fields and properties, the behaviour is undefined. The JPA 2.0 specification has the @Access annotation that makes it possible mix access types within an entity or entity hierarchy.

But the interesting question remains; which access type to use? A question that has been discussed before, but one I couldn't resist commenting on too. ;-)

  • Encapsulation - Property access is said to provide better encapsulation, because directly accessing fields is bad, right? Well actually, using property access obliges you to write getters and setters for all your persistent properties. These methods not only allow the JPA provider to set the fields, they also allow any other user of your entity class to do this! Using field access allows you to write only the getters and setters you want to (they're evil, remember?) and also write them as you want them, for example by doing validation in your setters or some calculation in your getters. In contrast, making these methods smarter when using property access is just asking for trouble.
  • Performance - Some people prefer field access because it supposedly offers better performance than property access. But that is a very bad reason to choose field access. Modern optimizing JVMs will make property access perform just as fast as field access and in any case database calls are orders of magnitude slower than either field access or method invocations.
  • Lazy loading in Hibernate - Hibernate's lazy loading implementation always initializes a lazy proxy when any method on that proxy is invoked. The only exception to this is the method annotated with the @Id annotation when you use property access. But when you use field access there is no such method and Hibernate initializes the proxy even when invoking the method that returns the identity of the entity. While some propose to use property access until this bug is fixed, I am not in favour of basing design decisions on framework bugs. If this bug really hurts your performance you might want to try and get the id of entity with the following code:
    Serializable id = ((HibernateProxy) entity).getHibernateLazyInitializer().getIdentifier()
     

    It's nasty, but at least this code will be localized to where you really need it.

  • Field access in Hibernate - It is good to know that while field access is OK for Hibernate to populate your entities, your code should still access those values through methods. Otherwise you will fall into the first of the Hibernate proxy pitfalls mentioned by my colleague Maarten Winkels.

To summarize I think field access is the way to go because it offers better encapsulation (without it properly managing bidirectional associations is impossible) and the performance impact is negligible (#1 on the performance problems top 10 is still the interplay between the database and your Java app). The only downside are some snafu's in Hibernate's lazy loading implementation that require you to take extra care when using field access.

What access type do you prefer? Do you see any difference in the way field access and property access are implemented in JPA providers other than Hibernate? Please let me know by leaving a comment below. See you at the next JPA implementation patterns blog in which I will talk about mapping inheritance hierarchies in JPA.

From http://blog.xebia.com

Published at DZone with permission of Vincent Partington, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Peter Veentjer replied on Wed, 2009/09/09 - 3:58am

Hi Vincent,

I also prefer the direct field access approach. An object is valid when it is is persisted and it should still be valid when it is rematerialized. So no need for additional check and no need to struggly with partial materialized objects and smart setters. 

Peter Veentjer

Multiverse Software Transactional Memory.

Jeroen Wenting replied on Wed, 2009/09/09 - 6:40am

While field access looks nicer in code, it's not nicer when executed. Where property access uses the methods annotated, field access requires reflection. That's quite a massive performance penalty you're imposing on your application, one that could very well mean the difference between acceptable and unacceptable runtime performance.
This of course also puts a lie to the argument that field access is faster, because it's actually slower.
Remains the only reason to use field access which is that you may not want a getter and setter for the field (maybe it's a calculated value that's never published, used only by some reporting engine or whatever that queries the datastore directly, but in that case it's arguably better that consumer calculate the value rather than you.

Robin Bygrave replied on Wed, 2009/09/09 - 8:29am in response to: Jeroen Wenting

@Jeron  Actually field access does not require reflection - code generation can be used instead (for both the "enhancement approach" and the "dynamic proxy approach") - certainly that has a performance improvement over reflection but ... reflection on the server JVM is pretty quick. The differences here end up pretty small when compared with query execution performance.

I'd agree that it generally comes down to whether you put logic in your entity beans and the extra care you need to take with property access when you do that.

For interest some of the Field vs Property debate has occured on a previous thread ... but IMO it didn't quite get concluded unfortunately. Maybe this time :)

http://eclipse.dzone.com/tips/12-feb-jpa-20-why-accesstype

 

Cheers, Rob.

Robin Bygrave replied on Wed, 2009/09/09 - 8:33am in response to: Peter Veentjer

@Peter

> So no need for additional check

What additional check? Property Access has an additional check?

 

> and no need to struggly with partial materialized objects

Can you explain this a bit more?  I don't understand ...

Peter Veentjer replied on Wed, 2009/09/09 - 10:12am in response to: Robin Bygrave

@Robin

 >What additional check? Property Access has an additional check?

 It could be. Especially if you have a non anemic domain model. 

 >and no need to struggly with partial materialized objects

 If setters are used when an object is 'rematerialized' from the database, all fields need to be set one after another. So untill all fields are set, the object is in an 'undefined' state. If you have added logic to the setters, and non materialized fields are read, strange things could happen.

 

class Person{
   int dateOfBirth;
   int dateOfDeath;

   public void setDateOfBirth(int newDateOfBirth){
        if(newDateOfBirth>dateOfDeath){
             throw error
        }
        this.dateOfBirth = newDateOfBirth;
   }

   public void setDateOfDeath(int newDateOfDeath){
       ...something similar
   }
}
If a Person is rematerialized, the fields are not set to the correct value (yet). If the dateOfBirth is set first, you get an error because the newDateOfBirth will be larger than the dateOfDeath. The only reason why this problem can happen is that the Person object is not (yet) in a valid state when methods are called and this could cause all kinds of strange problems. So that is why I prefer field level access.

Andy Jefferson replied on Wed, 2009/09/09 - 11:13am in response to: Peter Veentjer

If using a JPA implementation that employs bytecode enhancement I fail to see how this "partial materialization" problem can happen. All field access is enhanced, hence triggering any load of fields.

--Andy (DataNucleus)

Robin Bygrave replied on Wed, 2009/09/09 - 5:31pm in response to: Peter Veentjer

@Peter - ok, I see where you are coming from. The assumption being that the ORM itself is using the setter method to populate the bean when Property Access is used.

Hmmm... I wonder what exactly the JPA spec says... does it say say the ORM will use the setter method to populate the bean. I guess this is implied by the definition of Java Beans Property. 

The other approach an JPA vendor can make is to internally not use the setter method (when populating the bean) - so the setter method (and the logic in it) is only used by application code calling the setter. Another method is generated and used internally to populate the bean (so it might be possible to get different behaviour from different JPA vendors).

The reason an vendor might do this (not use the setter but use its own method to populate the bean) would be to provide support for PropertyChangeListeners etc.

@Andy - for PropertyAccess does DataNucleus use the setter?

NB: For what its worth Ebean ORM doesn't use the setter (generates it's own method) but its not strictly a JPA implementation.

Andy Jefferson replied on Thu, 2009/09/10 - 4:48am in response to: Robin Bygrave

> for PropertyAccess does DataNucleus use the setter?

DataNucleus doesn't "use" any setter since that is dependent on a user defining one. Look at the JDO spec for standardised bytecode enhancement providing field access detection.

--Andy (DataNucleus)

Mladen Girazovski replied on Thu, 2009/09/10 - 6:47am

I think that field access is a more natural representation of what persistence is about: Persisting the internal state of an object.

Saying that it breaks encapsulation is imho a proof that the concept of persistence has been misunterstood.

The fact that HIbernate requires a workaround is just another point on my personal "Workarounds & things to keep in mind when using Hibernate" list, i'm glad i don't use Hibernate anymore, it's getting anoying to have to use tricks & workarounds in my projects just to make them work with hibernate, "non invasive" persistence is different.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.