Currently i'm worrking on a Java project which uses JPA and under the hood Hibernate as its ORM.
Furthermore we're using Enverse as our auditing Library.
Now, when i query an entity which contains a #ManyToMany or #OneToMany relation directly through Hibernate, the embedded collections will get mapped to "Bag-Types" (PersistentBag for Lists and PersistentSet for Sets).
These Wrapper implement the "PersistentCollection" Interface, which handles the lazy Loading.
When the parentobject ist accessed, no database query will be executed (seen in the debugger). Only when i access an element of the collection, a database query is submittet.
But when i query the Revision through an AuditReader, the Collections will be wrapped in a ListProxy or a SetProxy, this leads to an "unexpected" behaviour (since enverse is a core element of hibernate). In this case, when i just access the parent object, every element in the embedded collection is directly queried. This leads to an enormous performance drop.
The Response from the Revision Endpoint is wrapped into RepresntationModel (from the Spring Hateos project). This leads to the access of the parent object and the generell collection, to create the "_embedded" Object of the response. With the PersistentBag there is no problem, but with the ListProxy, every Element gets queried from the database, leading to thousands of requests.
Is there a way to "teach" enverse to use PeristentBag (or PersistentSet) instead of the internal Proxy Collections or is there another workaround to not load the entire Collection?
Ignoring the embedded Ressources in the Revision boosts the performance, but is no solution since the references are Lost.
Enverse ignores the "fetch" configurations on Collection-Annotations (every Collection is fetched lazy), so this also does not do the trick.
Since the revision endpoint is highly generic, using projections is not an option.
Related
We are using JPA + Hibernate.
I have some Many-to-one mappings which are lazy loaded.
In Service, I Initiallize the Many-to-one objects by calling their getter method. but proxy gets assigned to parent VO and not actual VO Object.
My Question is, Is there any way in JPA to force to use no proxy Strategy.
My limitation here is i cant use Hibernate Objects or annotaions like #LazytoOne etc.
thanks in advance.
You cannot prevent Hibernate from using proxy objects there due to the fact that somehow it has to guarantee it's a lazy relation.
You have multiple choices:
Trigger the initialization Hibernate.initialize(parent.getChild()). Note that this is not the best way to do it and this also requires an active transaction.
Fetch the relation when fetching the entity itself. This can be done with the Fetch Joins. JPQL/HQL/Criteria API are capable of doing this.
Use read-only projections which contains only the data you need. For this particular case you can use Spring Data JPA as it comes with such a feature.
I suggest you to go with either option 2 or 3 as they are the most effective ways to do this.
Furher reading about lazy-loading here.
We are trying to filter\manipulate Persistent Collection based upon the objects it contains (filter out specific entries).
Since this manipulation will be performed on a large number of different objects containing different collections it must be as generic as possible.
Filtering on HQL\SQL level is not an option since it will be impossible to maintain. This means it must be performed after the collection was loaded and initialized.
We are currently using many of the Hibernate Events to handle single objects,
so we tried listening on the InitializeCollectionEvent.
But as it turns out, most of our collections are initialized using HQL Fetch so this event won't be raised for them.
Is there any other Hibernate Event that we can use?
Any other place where the Collections are processed after they are loaded?
We are using Hibernate 4.1.7 .
I think it's not a good idea to filter collection on server side, when the collection was loaded. If you do that it means smth goes wrong, rethink you db model or entity structure. One of the best way to filter collection - use HQL. Or you can either use
#Where or #Loader, #Filter.
I have a server and clients that are both Java-based and communicate with each other over RMI. The server's data access layer is implemented with JPA and Hibernate and entities are often used as parameters.
The clients do not have Hibernate code and dynamic code download is disabled, so when the server sends an entity to its clients, the actual entity must be sent, not the proxy. Moreover, the entity must be sent as-is, without pre-loading all lazy-fetched attributes because they will never be needed by the clients in most cases.
Is it possible to implement these requirements with Hibernate?
you can fetch all properties in the query
from docs
If you are using property-level lazy fetching (with bytecode instrumentation), it is possible to force Hibernate to fetch the lazy properties in the first query immediately using fetch all properties.
from Document fetch all properties order by name
http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/queryhql.html
or use eagle fetch in your mapping...
The only clean way I know of (that is without fetching every association for the object) is to use a separate object layer for data transportation.
Alternatively you can send the same object types repopulated by you with the necessary data, instead of hibernates objects with the proxies set.
My question is this: Is there ever a role for JPA merge in a stateless web application?
There is a lot of discussion on SO about the merge operation in JPA. There is also a great article on the subject which contrasts JPA merge via a more manual Do-It-Yourself process (where you find the entity via the entity manager and make your changes).
My application has a rich domain model (ala domain-driven design) that uses the #Version annotation in order to make use of optimistic locking. We have also created DTOs to send over the wire as part of our RESTful web services. The creation of this DTO layer also allows us to send to the client everything it needs and nothing it doesn't.
So far, I understand this is a fairly typical architecture. My question is about the service methods that need to UPDATE (i.e. HTTP PUT) existing objects. In this case we have these two approaches 1) JPA Merge, and 2) DIY.
What I don't understand is how JPA merge can even be considered an option for handling updates. Here's my thinking and I am wondering if there is something I don't understand:
1) In order to properly create a detached JPA entity from a wire DTO, the version number must be set correctly...else an OptimisticLockException is thrown. But the JPA spec says:
An entity may access the state of its version field or property or
export a method for use by the application to access the version, but
must not modify the version value[30]. Only the persistence provider
is permitted to set or update the value of the version attribute in
the object.
2) Merge doesn't handle bi-directional relationships ... the back-pointing fields always end up as null.
3) If any fields or data is missing from the DTO (due to a partial update), then the JPA merge will delete those relationships or null-out those fields. Hibernate can handle partial updates, but not JPA merge. DIY can handle partial updates.
4) The first thing the merge method will do is query the database for the entity ID, so there is no performance benefit over DIY to be had.
5) In a DYI update, we load the entity and make the changes according to the DTO -- there is no call to merge or to persist for that matter because the JPA context implements the unit-of-work pattern out of the box.
Do I have this straight?
Edit:
6) Merge behavior with regards to lazy loaded relationships can differ amongst providers.
Using Merge does require you to either send and receive a complete representation of the entity, or maintain server side state. For trivial CRUD-y type operations, it is easy and convenient. I have used it plenty in stateless web apps where there is no meaningful security hazard to letting the client see the entire entity.
However, if you've already reduced operations to only passing the immediately relevant information, then you need to also manually write the corresponding services.
Just remember that when doing your 'DIY' update you still need to pass a Version number around on the DTO and manually compare it to the one that comes out of the database. Otherwise you don't get the Optimistic Locking that spans 'user think-time' that you would have if you were using the simpler approach with merge.
You can't change the version on an entity created by the provider, but when you have made your own instance of the entity class with the new keyword it is fine and expected to set the version on it.
It will make the persistent representation match the in-memory representation you provide, this can include making things null. Remember when an object is merged that object is supposed to be discarded and replaced with the one returned by merge. You are not supposed to merge an object and then continue using it. Its state is not defined by the spec.
True.
Most likely, as long as your DIY solution is also using the entity ID and not an arbitrary query. (There are other benefits to using the 'find' method over a query.)
True.
I would add:
7) Merge translates to insert or to update depending on the existence of the record on DB, hence it does not deal correctly with update-vs-delete optimistic concurrency. That is, if another user concurrently deletes the record and you update it, it must (1) throw a concurrency exception... but it does not, it just inserts the record as new one.
(1) At least, in most cases, in my opinion, it should. I can imagine some cases where I would want this use case to trigger a new insert, but they are far from usual. At least, I would like the developer to think twice about it, not just accept that "merge() == updateWithConcurrencyControl()", because it is not.
I am developing an application in Flex, using Blaze DS to communicate with a Java back-end, which provides persistence via JPA (Eclipse Link).
I am encountering issues when passing JPA entities to Flex via Blaze DS. Blaze DS uses reflection to convert the JPA entity into an ObjectProxy (effectively a HashMap) by calling all getter methods on the entity. This includes any lazy-initialised one/many-to-many relationships.
You can probably see where I am going. If I pass a single object through JPA this will call all one/many-to-many methods on this object. For each returned object if they have one/many-to-many relationships they will be called too. As such, by passing back a single JPA entity I actually end up doing multiple database calls and passing all related entries back as a single ObjectProxy instance!
My solution to date is to create a translator to convert each entity to an ObjectProxy and vice-versa. This is clearly cumbersome and there must be a better way.
Thoughts please?
As an alternative, you could consider using GraniteDS instead of BlazeDS: GraniteDS has a much more powerful data management stack than BlazeDS (it competes more with LCDS) and fully support lazy-loading for all major JPA engines: Hibernate, EclipseLink, OpenJPA, etc.
Moreover, GraniteDS has a great client-side transparent lazy loading feature and even a so-called reverse lazy-loading mechanism.
And you don't need any kind of intermediate DTOs: it serializes JPA entities as is and uses code-generated ActionScript beans on the client-side to keep their initialization states.
Unfortunately, lazy-loading is not easy to accomplish with Flash clients. There are some working solutions, like dpHibernate, but so far all the different solutions I have tested fall short of what you would expect in terms of performance and ease of use.
So in my experience, it is the best and most reliable solution to always use DTOs, which adds the benefit of cleanly separating the database and view layers. This necessitates, though, that you implement either eager loading, or a second server round trip to resolve your many-to-many relations, as well as a good deal more boilerplate code to copy the DAO and DTO field values.
Which one to choose depends on your use case: Sometimes getting only the main object's fields might be enough, then you could simply omit the List of related objects from your DTO (transfer only those values you need for your query). Sometimes you may actually need the entire list of related entities, and then you could get it via eager loading, or by setting up a second remote object to find only the list.
EclipseLink also provides a copyObject() API that allows you to give a copy group of exactly what attribute you want. You could then use this copy to avoid having the relationships that you do not want.
If you have a detached object, you could just null out the fields that you do not want as well, or use a DTO.