Hibernate, writing domain objects to an interface for lazy loading - java

Why does hibernate require it's entities to be written to an interface in order for them to work correctly with lazy loading?

The only scenario where hibernate requires interfaces is collections. It's because hibernate uses its own collection implementations for lazy loading - PersistentBag, PersistentSet, etc. and assigns them to your fields. The implementations hold a reference to the session so that they can fill their data whenever required.
Hibernate can assign PersistentSet to private Set<Foo> set; (they do it with reflection), but it is not possible to do so for private HashSet<Foo> set;, because PersistentSet does not extend HashSet
As for lazy #*ToOne associations - hibernate creates a proxy object, using javassist (or cglib), and it does not require an interface. This is a rarely used feature anyway, and the proxy is a subclass of the real object, so unless you use getclass() (which you should not do), it works fine.

Related

Which list should be used for hibernate?

We recently joined up to an existing project and in several entity classes we have seen the following code example:
#OneToMany(mappedBy = "department")
private List<Employee> employee= new LinkedList<>();
I had a discussion with a developer about using ArrayList instead of LinkedList for hibernate. But the arguments from both sides were not clear enough.
Usually, i use for many purposes an ArrayList. Here is a good comparison
Does hibernate under the hood work better with that?
Is there a reason why linkedList is used?
Or has it simply been used unknowingly in the project?
The actual implementation used when an entity is loaded from the database is not the same as the default value in the class definition. This is why entity properties which are collections must be specified as an interface type.
Hibernate uses its own collection implementations which are enriched with lazy-loading, caching or state change detection semantics. For this reason, persistent collections must be declared as an interface type.
From https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#collections
If your entity is not loaded from the database then you should specify a default implementation that make sense for the use case, but being aware it'll not be the same implementation when the entity is loaded. Generally, this means just using ArrayList in most situations.

Hibernate: Does Hibernate Always Use Object Proxies?

I thought that object proxies are used only when the class has a field of Collection type, and uses Lazy fetching. But some sources seem to suggest that Hibernate 3 uses proxies for all objects regardless of whether the object has field of collection type or not.
Can someone please explain when Hibernate uses object proxies? Is it all the time, or just in some cases?
As per the Hibernate docs :
By default, Hibernate uses lazy select fetching for collections and lazy proxy fetching for single-valued associations. These defaults make sense for most associations in the majority of applications.
So if you have a single object marked as an association (one-to-one or many-to-one) then it will be a proxy object until you try to access it, at which point Hibernate will attempt to populate it with values from the database.
AFAIK a collection will be initialized as null until you try to access it, at which point Hibernate will attempt to hydrate it with values.
As you suggest in your comment, yes, your object is entirely dependent on the proxy object to load the values when you request them.
None of this applies of course if you use fetchType.EAGER on the association. If you are new to Hibernate I suggest perusing this guide that I wrote. It covers things like fetch types and config for different types of relationships.

Can JPA entity beans contain methods to add objects to Collection fields?

I have several JPA entities that have one-to-many relationships to other entities and therefore contain Collection fields. Obviously, as per the standard bean pattern I have getter and setter methods for these Collections but it would also be useful to have methods to add and remove objects/entities from these collections. Would I be breaking bean conventions to add these methods to the entity class themselves? If this is the case, what would be the best way of implementing these methods? I do have Facade EJBs for each entity which I could use for this purpose but these are primarily concerned with DB access logic (persist, remove, etc) and obtaining data structures (lists, etc) rather than manipulating the entity itself.
Thanks to Nikos Paraskevopoulos and Flying Dumpling for the answer. It would appear that utility methods are permissible within an entity class.

What collections does jpa return?

Does JPA ( Eclipselink in this case) always return IndirectList where Entity have a List?
Is ok that list or It should be converted to another list( maybe linkedlist)?
Analysis
If we look at EclipseLink's IndirectList's API, it says:
To use an IndirectList: declare the appropriate instance variable with type IndirectList (jdk1.1) or Collection/List/Vector (jdk1.2).
TopLink will place an IndirectList in the instance variable when the
containing domain object is read from the datatabase. With the first
message sent to the IndirectList, the contents are fetched from the
database and normal Collection/List/Vector behavior is resumed.
If we view IndirectList sources, we will see, that all the work is delegated to it's original collection, just like API says.
Answers
Does JPA ( Eclipselink in this case) always return IndirectList where Entity have a List?
Yes, it always does return your specified collection wrapped with IndirectList. Since it delegates all its internal work to the wrapped collection, it preserves the way it works.
Is ok that list or It should be converted to another list( maybe
linkedlist)?
Yes, it is okay to use IndirectList. You don't convert, you just define any type of collection you want and don't worry about IndirectList, since it is managed transparently.
Since List is an interface the JPA provider is free to return any implementation. EclipseLink rerurns an IndirectList where a List is used. This is perfectly fine since the IndirectList is a List.
For the record or for future reference, it is generally best practice to use interfaces with JPA.

How does Hibernate detect dirty state of an entity object?

Is it using some kind of byte codes modification to the original classes?
Or, maybe Hibernate get the dirty state by compare the given object with previously persisted version?
I'm having a problem with hashCode() and equals() methods for complicated objects. I feel it would be very slow to compute hash code if the object has collection members, and cyclic references are also a problem.
If Hibernate won't use hashCode()/equals() to check the dirty state, I guess I should not use equals()/hashCode() for the entity object (not value object), but I'm also afraid if the same operator (==) is not enough.
So, the questions are:
How does Hibernate know if a property of an object is changed?
Do you suggest to override the hashCode()/equals() methods for complicated objects? What if they contains cyclic references?
And, also,
Would hashCode()/equals() with only the id field be enough?
Hibernate uses a strategy called inspection, which is basically this: when an object is loaded from the database a snapshot of it is kept in memory. When the session is flushed Hibernate compares the stored snapshot with the current state. If they differ the object is marked as dirty and a suitable SQL command is enqueued. If the object is still transient then it is always dirty.
Source: book Hibernate in Action (appendix B: ORM implementation strategies)
It's important to notice however that Hibernate's dirty-checking is independent of the methods equals/hascode. Hibernate does not look at these methods at all (except when using java.util.Set's, but this is unrelated to dirty-checking, only to the Collections API) The state snapshot I mentioned earlier is something similar to an array of values. It would be a very bad decision to leave such a core aspect of the framework in the hands of developers (to be honest, developers should not care about dirty-checking). Needless to say that equals/hascode can be implemented in many ways according to your needs. I recommend you to read the cited book, there the author discuss equals/hascode implementation strategies. Very insightful reading.
Hibernate default dirty checking mechanism will match all mapped properties of all currently attached entities against their initial loading-time values.
You can better visualize this process in the following diagram:
Hibernate does a field-by-field checking to determine the dirtiness of an entity.
So hashCode/equals do not come into the picture at all.
Actually, the field-by-field dirty checking done by Hibernate can be quite costly in terms of performance.
So it provides interfaces like Strategy or Interceptor.findDirty() to handle the same.
Following post explains this in greater detail (alongwith some ideas for applications to optimize it fully): http://prismoskills.appspot.com/lessons/Hibernate/Chapter_20_-_Dirty_checking.jsp
Probably worth adding, as this distracted me for a while: if you are using a CustomType on your persistent object, equals is used for the dirty check.
This stack is from setting a breakpoint in the equals method of my custom data type in Hibernate, MyType, then triggering a transaction and seeing the equals being called.
equals:68, MyType (xxxxxx)
isEqual:105, CustomType (org.hibernate.type)
isSame:119, AbstractType (org.hibernate.type)
isDirty:79, AbstractType (org.hibernate.type)
isDirty:249, CustomType (org.hibernate.type)
findDirty:316, TypeHelper (org.hibernate.type)
findDirty:4622, AbstractEntityPersister (org.hibernate.persister.entity)
dirtyCheck:585, DefaultFlushEntityEventListener (org.hibernate.event.internal)
isUpdateNecessary:242, DefaultFlushEntityEventListener (org.hibernate.event.internal)
onFlushEntity:169, DefaultFlushEntityEventListener (org.hibernate.event.internal)
flushEntities:232, AbstractFlushingEventListener (org.hibernate.event.internal)
flushEverythingToExecutions:92, AbstractFlushingEventListener (org.hibernate.event.internal)
onAutoFlush:50, DefaultAutoFlushEventListener (org.hibernate.event.internal)
accept:-1, 765785095 (org.hibernate.internal.SessionImpl$$Lambda$1238)
fireEventOnEachListener:102, EventListenerGroupImpl (org.hibernate.event.service.internal)
autoFlushIfRequired:1327, SessionImpl (org.hibernate.internal)
does the dirty checking also involve any attached AttributeConverters? what if the value in the java object stays the same but the AttributeConverter logic is changed and does lead to different database values.
so read entity with old AttributeConverter config, write entity with new AttributeConverter config.
the java object stays the same for old and new AttributeConverter but the database values changes because of old and new AttributeConverter config.
It is simple-- when you load/get entity object by id and then set its new field values by setter method and close session without calling update() method. then hibernate automatically update the changed value in the table without affecting other fields. and at the same time entity object is in dirty state.

Categories