Using direct field access instead of getters in a copy constructor leads to null pointer exception

otonglet :

It must be Java 101 but I can't figure why I can't use direct field access and why I'm forced to use getters in a copy constructor.

I have a bunch of entities. They are organised like a tree. Linked entities are fetched eagerly.

I'm using Hibernate, Lombok and IntelliJ for the debugger.

When I pull one of the entity trees by the root I get a tree of objects. Let's call it "the original". For some reason related to business requirements I need to copy it (let's call this "the copy"). I do it using a copy constructor. I first wrote a version of the copy constructor using direct field access.

 this.someField= original.someField

It didn't work. When I checked the debugger I saw that original.someField (as well as the other fields) were always null.

enter image description here

Nevertheless, it works using the getters.

 this.setSomeField(original.getSomeField())

In the debugger, I can see the fields are "set" in original.handler.target. (I've no idea what handler.target is).

enter image description here

Could someone explain to me why a direct field access doesn't work ?
(I'm asking about the technical reason not the philosophical one like "you should always use getters" etc).

I'd also be glad to know what is "handler.target".

Thanks in advance.

Gergely Bacso :

What you have encountered is not at all Java 101 problem. Hibernate has a feature called lazyloading, that allows the framework to defer the loading of an (potentially heavy) object to a later point in time, only when it is needed. This comes handy when you are for example loading an account object just to check an active flag, but absolutely do not need all the login history fetched with this account.

Now the "only when it is needed" part: getters.

Hibernate knows that you do need that lazily loadable object when you do call the getter on the parent object in the object graph. Until you do so, the lazily referred object remains null. Direct variable access bypasses the proxylogic that performs this "trick", and that is how you get to the unexpected null values. when the field is accessed via its getter, the proxied code kicks in, loading happens, and you get your object back.

The handler/target/etc are just the extra references you need to hvae due to the proxying. (your account will not have an direct accounthistory variable anymore, but instead an accounthistory_proxy, which in turn will have an accounthistory_real)

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=145838&siteId=1