I have a class where a few members have annotation:
#ManyToOne(fetch = FetchType.EAGER)
In the specific part of my program, these load far too many data. Unfortunately, I can't change these annotations as this will influence performance of other parts of this program. Is there a way in eclipselink to change this to LAZY for 1 specific JPQL query?
To phrase this an other way, you can change LAZY to EAGER by using a fetch join. I'm hoping for something which changes EAGER to LAZY
It's not possible. My rule of thumb is : make everything LAZY, and use custom queries if you want eager fetching.
The best you can do is to load tuples (and populate DTOs) instead of loading entities.
I know that since eclipselink 2.3 you can extend your entities at runtime, maybe check that?
http://wiki.eclipse.org/EclipseLink/Examples/JPA/Extensibility
Related
I was reading over the docs regarding Eclipselink's support for #OrderColumn. It looks like this only applies to List and not Set. The reason I ask is because I have a ManyToMany bi-directional relationship (using a join table) which is a Set and is implemented with a HashSet because the collection can't have duplicates.
I wanted to order the entries in this set using #OrderColumn, but it appears I can only apply this to List, however using List will break my unique requirement. Is this understanding correct?
If so what is the recommended strategy for this case?
Thanks,
-Noah
This looks similar to the following question:
Why cannot a JPA mapping attribute be a LinkedHashset?
The Set interface does not define ordering of elements, so your set needs to be a concrete implementation like a TreeSet or LinkedHashSet implementation, not just any old Set. But your JPA provider is generally going to use its own collection implementations with special magic to handle lazy loading.
The above answer suggests that there may be some EclipseLink-specific workaround if you are willing to give up lazy loading.
I can think of two options, neither one perfect:
just use a List and rely on business logic to enforce uniqueness, with DB UNIQUE constraints as a backstop. Honestly, I end up using List for collections almost reflexively, even when Set would have been more appropriate; I admit it's sloppy but has yet to cause any significant problems for me in years of practice.
use a Set and change #ManyToMany to #OneToMany, and make your join table w/order column an actual entity that implements Comparable using the order column. Then, overload your getter method to do something like
if (! this.set instanceof TreeSet)
this.set = new TreeSet<T>(this.set);
return this.set;
I've learned about lazy loading, eager loading with .include and explicit loading with .load(), but something that confuses me is when you project in a query and explicitly request a navigation property like this:
var address = from a in context.Addresses
select {a, Name = a.Contact.Name}
Here Contact is a navigation property in Addresses that links to a Contact entity.
I tried with both lazy loading on and off and it works both ways. I wonder when I request my data like this, am I eager loading or deferred loading? My understanding that only one query will be made to the database which means it's eager loading, except in this case only the "Name" property of the Contact entity will be loaded, as opposed to the entire Contact entity if I were to use context.Addresses.include("Contact")? Does it make a query like this more efficient than eager loading with .include() ?
Some clarifications will be appreciated.
Lazy loading, eager loading and explicit loading works in the most common scenarios. Projection is replacement for eager loading because it can also load related entities with single query. Using projection make sense if you need to load entities with some complex query because eager loading doesn't work in these cases. Use projection if you need:
Any kind of join or aggregation in the linq query. As I know Include is ignored once you start using manual joins.
Any kind of filtering or sorting in navigation property. Include can only load all related entities from navigation property without any sorting. Once you need to apply any where condition or order by on related entities you can't use Include and you must use projection.
It's lazy evaulation as it won't execute until something enumerates over address.
Eager loading is normally used to describe an entity object's navigation properties being pre-loaded but in this case you are not directly materializing any entity objects as you are projecting onto an anonymous type.
If you access a.Contact.Name rather than Name you'll most likely cause another database hit as you haven't eager loaded the Contact object of Address, you specifically selected and projected the Name property onto an anonymous object.
I have a person object that has a list of addresses and in the mapping it is annotated to be fetched eagerly.
I have a criteriabuilder query where, say i want to fetch a person object but without fetching the address. how do i disable the eager feting in criteria query alone. is there a method?
The actual code is not this simple...this is just to give you an example.
Thanks in advance
It is normally better to use LAZY fetching in the mapping, and then fetch it eagerly when required using the JPQL "join fetch" option.
In JPA you could just select the data that you want from the entity, instead of the entire entity, then you could avoid the relationships. You could also use a constructor query to create shell instances (note these would not be managed).
A way to make an eager relationship lazy in a query is to use fetch groups. JPA does not support fetch groups, but some JPA providers such as EclipseLink do. In EclipseLink you can define a fetch group using the #FetchGroup annotation, or query hints.
I think it is possible. From OpenJPA documentation:
You can specify a default subclass fetch mode for an individual class with the metadata extension described in Section 9.1.1, “ Subclass Fetch Mode ”. Note, however, that you cannot "upgrade" the runtime fetch mode with your class setting. If the runtime fetch mode is none, no eager subclass data fetching will take place, regardless of your metadata setting.
This applies to the eager fetch mode metadata extension as well (see Section 9.2.1, “ Eager Fetch Mode”). You can use this extension to disable eager fetching on a field or to declare that a collection would rather use joins than parallel selects or vice versa
Section 9.2.1 here.
Is it possible to load an entity excluding some properties? One of this entity's properties is expensive to select. I would like to lazy load this property. Is that possible?
Now that you have read everyone's reply, I will give you the correct answer. EF does not support lazy loading of properties. However it does support a much powerful concept then this. It's called table splitting where you can map a table to two entities. Say a product table in the the database can be mapped to product entity and ProductDetail entity. You can then move the expensive fields to the ProductDetail entity and then create a 1..1 association between prodcut and productdetail entity. You can then lazy load the productdetail association only when you need it.
In my performance chapter of my book, I have a recipe called.
13-9. Moving an Expensive Property to Another Entity
Hope that helps!
Julie Lerman has an article on how to split a table
With a scalar property, the only way to selectively not load a certain property is to project in ESQL or L2E:
var q = from p in Context.People
select new
{
Id = p.Id,
Name = p.Name // note no Biography
};
+1 to Dan; doing this lazily is worse than loading it up-front. If you want to control loading, be explicit.
stimms is correct, but be careful while using lazy loading. You may have performance issues and not realize the property is getting loaded at a specific location in your code. This is because it loads the data when you use the property
I prefer to use explicit loading. This way you know when they get loaded and where. Here's a link that gives an example for the LoadProperty http://sankarsan.wordpress.com/2010/05/09/ado-net-entity-framework-data-loading-part-2/
You can also you Eager Loading by using the Include method. Example here:http://wildermuth.com/2008/12/28/Caution_when_Eager_Loading_in_the_Entity_Framework
Given a query over an EntityFramework DbSet, where the targeted entity contains a BigProperty and a SmallProperty,
When you're trying to only access the SmallProperty without loading the BigProperty in memory :
//this query loads the entire entity returned by FirstOrDefault() in memory
//the execution is deferred during Where; the execution happens at FirstOrDefault
db.BigEntities.Where(filter).FirstOrDefault()?.SmallProperty;
//this query only loads the SmallProperty in memory
//the execution is still deferred during Select; the execution happens at FirstOrDefault
//a subset of properties can be selected from the entity, and only those will be loaded in memory
db.BigEntities.Where(filter).Select(e=>e.SmallProperty).FirstOrDefault();
Therefore you could exploit this behaviour to only query the BigProperty where you actually need it, and use select statements to explicitly filter it out everywhere else.
I tested this with the Memory Usage functionality from the Visual Studio debug Diagnostic Tools.
I'm using DataNucleus as a JPA implementation to store my classes in my web application. I use a set of converters which all have toDTO() and fromDTO().
My issue is, that I want to avoid the whole DB being sent over the wire:
If I lazy load, the converter will try to access ALL the fields, and load then (resulting in very eager loading).
If I don't lazy load, I'll get a huge part of the DB, since user contains groups, and groups contains users, and so on.
Is there a way to explicitly load some fields and leave the others as NULL in my loaded class?
I've tried the DataNucleus docs with no luck.
Your DTOs are probably too fine-grained. i.e. dont plan to have a DTO per JPA entity. If you have to use DTOs then make them more coarse grained and construct them manually.
Recently we have had the whole "to DTO or not to DTO, that is the question" discussion AGAIN. The requirement for them (especially in the context of a JPA app) is often no longer there, but one of the arguments FOR DTOs tends to be that the view has coarser data requirements.
To only load the data you really require, you would need to use a custom select clause containing only these elements that you are about to use for your DTOs. I know how painful this is, especially when it involves joins, which is why I created Blaze-Persistence Entity Views which will take care of making the query efficient.
You define your DTO as an interface with mappings to the entity, using the attribute name as default mapping, this looks very simple and a lot like a subset of an entity, though it doesn't have to. You can use any JPQL expression as mapping for your DTO attributes.