[
https://hibernate.onjira.com/browse/HHH-7206?page=com.atlassian.jira.plug...
]
Guenther Demetz edited comment on HHH-7206 at 3/29/12 9:08 AM:
---------------------------------------------------------------
Here following a concrete example in which these enhancement show the impact on
performance.
Assume we have a entity class representing the yearly final stocks of a magazine.
{code}
@Entity
class FinalStock {
@Id
long id;
@Version
int version;
@NaturalId(mutable=true)
String articleNumber;
@NaturalId(mutable=true)
int year;
@OneToMany(cascade=All)
@org.hibernate.annotations.OptimisticLock(excluded=false)
Set<Inventory> inventories;
}
{code}
Immagine that we want compare all final stocks between the years 2011 and 2010,
in order to avoid multiple database hits, we fetch all interested entities into persistent
context with a single query,
that's reasonable.
{code}
//session.setFlushMode(Auto) leaving it to the default flush mode
List<FinalStock> list = session.createQuery("from FinalStock where year in
(2011,2010)").list(); // loading 1.000 FinalStocks
for (FinalStock stock : list) {
String corresponding_article_other_year = calculate(stock); //algorythm which cannot
replaced by a sofisticated outer join query
FinalStock stockOtherYear =
session.byNaturalId(FinalStock.class).using("articleNumber",corresponding_article_other_year).
using("year",getOtherYear(stock.year)).load();
if (stockOtherYear != null) { // true for 90% of cases
//do some work here causing some dirty FinalStock objects and dirty collections
if (condition) {
Inventory inv = new Inventory(....);
stock.add(inv);
}
}
}
session.getTransaction.commit();
...
{code}
As we have all concerning entities already loaded in context,
and as there's an excpectance around 90% to retrieve the corresponding stock,
we should expect the NaturalId lookups performing very fast.
In truth without proposed enhancements, hibernate would spend most of it's time in
1000 unnecessary and expensive dirty check/session flushes.
With the first enhancement implemented, hibernate still would spend substantial time in
synchronizing 1000 times (for each naturalIdLoadAccess) the 1000 FinalStocks which are in
context.
With the second enhancement implemented too(using setAutoSynchronization set to false),
the whole thing begins to work in reasonable way.
The last wormwood to eliminate are the queries (database-hits) which are performed in
those 10% of the cases,
where the corresponding NaturalId get not resolved from cache.
Since in our concrete case we have already loaded all interested objects in context, those
queries are overhead.
So finally it would be fine to have a further method on NaturalIdLoadAccess allowing do
prevent loads from datasource.
This 3 enhancements put together in my opinion would open new horizons in hibernate,
allowing to do fast in-memory operations which previously were only possible with huge
user-code.
Please give us your feedback ...
was (Author: pb00067):
Here following a concrete example in which these enhancement show the impact on
performance.
Assume we have a entity class representing the yearly final stocks of a magazine.
{code}
@Entity
class FinalStock {
@Id
long id;
@Version
int version;
@NaturalId(mutable=true)
String articleNumber;
@NaturalId(mutable=true)
int year;
@OneToMany(cascade=All)
@org.hibernate.annotations.OptimisticLock(excluded=false)
Set<Inventory> inventories;
}
{code}
Immagine that we want compare all final stocks between the years 2011 and 2010,
in order to avoid multiple database hits, we fetch all interested entities into persistent
context with a single query,
that's reasonable.
{code}
//session.setFlushMode(Auto) leaving it to the default flush mode
List<FinalStock> list = session.createQuery("from FinalStock where year in
(2011,2010)").list(); // loading 1.000 FinalStocks
for (FinalStock stock : list) {
String correspondging_article_other_year = calculate(stock); //algorythm which cannot
replaced by a sofisticated outer join query
FinalStock stockOtherYear =
session.byNaturalId(FinalStock.class).using("articleNumber",correspondging_article_other_year).
using("year",getOtherYear(stock.year)).load();
if (stockOtherYear != null) { // true for 90% of cases
//do some work here causing some dirty FinalStock objects and dirty collections
if (condition) {
Inventory inv = new Inventory(....);
stock.add(inv);
}
}
}
{code}
As we have all concerning entities already loaded in context,
and as there's an excpectance around 90% to retrieve the corresponding stock,
we should expect the NaturalId lookups performing very fast.
In truth without the first enhancement above, hibernate would spend most of it's time
in 1000 unnecessary and expensive dirty check/session flushes.
With the first enhancement implemented, hibernate still would spend substantial time in
synchronizing 1000 times (for each naturalIdLoadAccess) the 1000 FinalStocks which are in
context.
With the second enhancement implemented too(using setAutoSynchronization set to false),
the whole thing begins to work in reasonable way.
The last wormwood to eliminate are the queries (database-hits) which are performed in
those 10% of the cases,
where the corresponding NaturalId get not resolved from cache.
Since in our concrete case we have already loaded all interested objects in context, those
queries are overhead.
So finally it would be fine to have a further method on NaturalIdLoadAccess allowing do
prevent loads from datasource.
This 3 enhancements put together in my opinion would open new horizons in hibernate,
allowing to do fast in-memory operations which previously were only possible with huge
user-code.
Please give us your feedback ...
NaturalIdLoadAccess: NaturalId synchronization with no need to flush
at all
---------------------------------------------------------------------------
Key: HHH-7206
URL:
https://hibernate.onjira.com/browse/HHH-7206
Project: Hibernate ORM
Issue Type: Improvement
Components: core
Affects Versions: 4.1.1
Environment: Hibernate4, database-independent
Reporter: Guenther Demetz
Labels: flush, naturalId
With few code changes I think it is possible to make NaturalIdLoadAccess work with no
need to rely on flush at all,
please see following comments.
--
This message is automatically generated by JIRA.
For more information on JIRA, see:
http://www.atlassian.com/software/jira