[Hibernate-JIRA] Created: (HHH-4030) Implement support for native recursive query functionality of popular DBMSes
by David Cracauer (JIRA)
Implement support for native recursive query functionality of popular DBMSes
----------------------------------------------------------------------------
Key: HHH-4030
URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-4030
Project: Hibernate Core
Issue Type: New Feature
Components: core, query-hql, query-sql
Environment: Hibernate 3.3.2, MSSQL
Reporter: David Cracauer
We have a couple of areas in our system where need to load tree structures from our database. These trees can be very deep (often 20+ levels). SQL Server 2005 introduced Common Table Expressions, a kind of in-line view that can be used recursively.
These allow us to quickly get a result set like this:
id, label, parentId
1, foo, null
2, foo2, 1
3, foo3, 2
4, foo4, 2
5, foo5, 4
6, foo6, 1
>From a tree like this:
[1, foo]
|
| -[2, foo2]
| | - [3, foo3]
| | - [4, foo4]
| | - [5, foo5]
|- [6, foo6]
using a query like this (not tested):
with MyCTE(
id,
label,
parentId)
as
( select n.id, n.label, n.parentid
from Node n
UNION ALL
select c.id, c.label, c.parentId
from MyCTE c
inner join Node n on n.id=c.parentId)
select * from MyCTE
It happens many times more quickly than we've been able to load the graphs with Hibernate, even using batching etc.
We've tried using hibernate's built in native sql support without success. The alias injection breaks the Common Table Expression definition ( with MyCTE ), as it is a view definition and doesn't allow for the 'id as id_276' syntax, rather requiring just a column name.
I know that there are several other major DBMSes that support recursive querying now. Is there a way to have support for this functionality in hibernate core?
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators....
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
12 years, 7 months
[Hibernate-JIRA] Created: (HHH-3961) SQLServerDialect, support nowait in LockMode.UPGRADE_NOWAIT
by Guenther Demetz (JIRA)
SQLServerDialect, support nowait in LockMode.UPGRADE_NOWAIT
------------------------------------------------------------
Key: HHH-3961
URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-3961
Project: Hibernate Core
Issue Type: Improvement
Components: core
Affects Versions: 3.3.1
Environment: 3.3.1 GA , SQLServer2008
Reporter: Guenther Demetz
Priority: Trivial
The method SQLServerDialect#appendLockHint currently ignores the LockMode.UPGRADE_NOWAIT returning the same string as for
LockMode.UPGRADE.
public String appendLockHint(LockMode mode, String tableName) {
if ( mode.greaterThan( LockMode.READ ) ) {
// does this need holdlock also? : return tableName + " with (updlock, rowlock, holdlock)";
return tableName + " with (updlock, rowlock)";
}
else {
return tableName;
}
}
As SQLServer supports the nowait option I propose the following improvement:
public String appendLockHint(LockMode mode, String tableName) {
if ( mode == LockMode.UPGRADE_NOWAIT) {
return tableName + " with (updlock, rowlock, nowait)";
}
else if ( mode.greaterThan( LockMode.READ ) ) {
// does this need holdlock also? : return tableName + " with (updlock, rowlock, holdlock)";
return tableName + " with (updlock, rowlock)";
}
else {
return tableName;
}
}
A test gave me a correct behaviour: if the concerning row is already locked,
then after Lock request time out period exceeded following exception is thrown:
org.hibernate.exception.SQLGrammarException: could not lock: [persistent.jpa.AssociationsClassPeer#1]
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:90)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.dialect.lock.SelectLockingStrategy.lock(SelectLockingStrategy.java:115)
at org.hibernate.persister.entity.AbstractEntityPersister.lock(AbstractEntityPersister.java:1361)
at org.hibernate.event.def.AbstractLockUpgradeEventListener.upgradeLock(AbstractLockUpgradeEventListener.java:108)
at org.hibernate.event.def.DefaultLockEventListener.onLock(DefaultLockEventListener.java:87)
at org.hibernate.impl.SessionImpl.fireLock(SessionImpl.java:611)
at org.hibernate.impl.SessionImpl.lock(SessionImpl.java:603)
...
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Lock request time out period exceeded.
at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:196)
at com.microsoft.sqlserver.jdbc.SQLServerResultSet$FetchBuffer.nextRow(SQLServerResultSet.java:4700)
at com.microsoft.sqlserver.jdbc.SQLServerResultSet.fetchBufferNext(SQLServerResultSet.java:1683)
at com.microsoft.sqlserver.jdbc.SQLServerResultSet.next(SQLServerResultSet.java:956)
at com.p6spy.engine.spy.P6ResultSet.next(P6ResultSet.java:156)
at com.p6spy.engine.logging.P6LogResultSet.next(P6LogResultSet.java:124)
at com.mchange.v2.c3p0.impl.NewProxyResultSet.next(NewProxyResultSet.java:2859)
at org.hibernate.dialect.lock.SelectLockingStrategy.lock(SelectLockingStrategy.java:97)
... 24 more
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators....
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
12 years, 7 months
[Hibernate-JIRA] Created: (HHH-6848) The duration of hibernate merge rises quadratically with the amount of entities in a to be merged objectgraph
by Wim Ockerman (JIRA)
The duration of hibernate merge rises quadratically with the amount of entities in a to be merged objectgraph
-------------------------------------------------------------------------------------------------------------
Key: HHH-6848
URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-6848
Project: Hibernate Core
Issue Type: Improvement
Components: core
Affects Versions: 4.0.0.CR6, 3.6.8
Environment: Any Hibernate version, any database platform.
Reporter: Wim Ockerman
Attachments: HibernateMergeMeasurementBeforeAndAfterSolution.png, Sample_JProfiler_hotspot_research_in_a_merge_of_a_big_object_graph.png
Tests with merging large objectgraphs showed quadratic rise of duration of the merge related to the object-graph size.
>From a certain number of objects in the graph this becomes substantial.
This limits hibernate scalability for larger object-graph usages.
Analysis (based on 3.6.8 code branch):
The merge algorithm of hibernate is a recursive objectgraph walking algorithm. During it's execution it builds up algorithm state information e.g. of merged entities to original objects in the input graph. The information is stored in the EventCache object in the *entityToCopyMap* member. ( org.hibernate.event.def.EventCache)
At certain places in the merge algorithm the inverse relation as hold in the EventCache object is needed.
see e.g. def.AbstractSaveEventListener.performSaveOrReplicate -> calling persister.getPropertyValuesToInsert(.., *getMergeMap()*,..)
The getMergeMap() call calls through to the EventCache's invertMap method.
In the implementation of invertMap() a new map is created on the spot and all the elements in the entityToCopyMap where put in, now as copy to entity direction.
The call invertMap() happens more in a big detached graph wile merging, and also the size of the entityToCopyMap rises with the number of object already merged in the graph. Thus we have a quadratic relation between the total inverMap() execution time and the number of objects in a graph to be merged.
JProfiler screenshot sample attached showing a high call count and high duration time on the invertMap method in a merge vs time it took for a flush of the merged object graph. The latter was unexpected, as the flush time is a good higher bound reference for an object graph operation.
To solve this problem see proposed solution in pull request #208 of [hibernate-core] Performance Optimization of in memory merge algorithm.
With the solution, the merge duration behaves more linear with respect to the size of the to be merged objectgraph.
See attached plot of the original hibernate merge behaviour vs entities in a graph (redline) and the proposed solution's timeing.
--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira
12 years, 7 months
[Hibernate-JIRA] Created: (HHH-3718) call to id getter initializes proxy when using AccessType( "field" )
by Paul Lorenz (JIRA)
call to id getter initializes proxy when using AccessType( "field" )
--------------------------------------------------------------------
Key: HHH-3718
URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-3718
Project: Hibernate Core
Issue Type: Bug
Components: core
Affects Versions: 3.3.1
Environment: hibernate 3.3.1, hibernate annotations 3.4.0, running on windows, linux and solaris, using sybase 15
Reporter: Paul Lorenz
Calling getter for id when using AccessType( "field" ) causes proxy initialization.
In org.hibernate.proxy.proxy.pojo.BasicLazyInitializer there is the code
else if ( isUninitialized() && method.equals(getIdentifierMethod) ) {
return getIdentifier();
}
However, when using field access, the getIdentifierMethod will be null. I fixed this for us by changing DirectPropertyAccessor by adding a Method attribute to the DirectGetter inner class, and looking up the appropriate getter in the constructor. As far as I can tell, getMethod is only used in two places. In the above case, to the get the identity getter and in PojoComponentTupilizer.isMethodOf. This doesn't seem to break anything. I don't know if this is a clean solution, seems a little hacky to me, however, it would be great if the issue could be fixed somehow.
public static final class DirectGetter implements Getter {
private final transient Field field;
private final Class clazz;
private final String name;
private Method method;
DirectGetter(Field field, Class clazz, String name) {
this.field = field;
this.clazz = clazz;
this.name = name;
try
{
BeanInfo beanInfo = Introspector.getBeanInfo( clazz );
PropertyDescriptor[] pdArray = beanInfo.getPropertyDescriptors();
if ( pdArray != null )
{
for (PropertyDescriptor pd : pdArray )
{
if ( pd.getName().equals( name ) )
{
this.method = pd.getReadMethod();
}
}
}
}
catch ( Exception e )
{
// ignore
}
}
public Object get(Object target) throws HibernateException {
try {
return field.get(target);
}
catch (Exception e) {
throw new PropertyAccessException(e, "could not get a field value by reflection", false, clazz, name);
}
}
public Object getForInsert(Object target, Map mergeMap, SessionImplementor session) {
return get( target );
}
public Method getMethod() {
return method;
}
public String getMethodName() {
return method == null ? null : method.getName();
}
public Class getReturnType() {
return field.getType();
}
Object readResolve() {
return new DirectGetter( getField(clazz, name), clazz, name );
}
public String toString() {
return "DirectGetter(" + clazz.getName() + '.' + name + ')';
}
}
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators....
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
12 years, 7 months