Changeset 7465


Ignore:
Timestamp:
Mar 28, 2018, 9:26:14 AM (4 years ago)
Author:
Nicklas Nordborg
Message:

References #2110: QueryException? in annotation importer plug-in

Implemented a method for removing old "synthetic" parameters that Hibernate generates under the hood (https://github.com/hibernate/hibernate-orm/blob/5.2/hibernate-core/src/main/java/org/hibernate/query/internal/QueryParameterBindingsImpl.java#L525).

The method uses the Java reflektion API to get access to a private variable inside an internal Hibernate class (QueryParameterBindingsImpl.parameterBindingMap). This solution may stop working if Hibernate is updated. The TestAnnotationFlatFileImporter is expected to fail in that case.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/3.12-stable/src/core/net/sf/basedb/core/hibernate/NativeQueryWrapper.java

    r7464 r7465  
    2222package net.sf.basedb.core.hibernate;
    2323
     24import java.lang.reflect.Field;
    2425import java.util.Calendar;
    2526import java.util.Collection;
    2627import java.util.Date;
     28import java.util.Iterator;
    2729import java.util.List;
    2830import java.util.Map;
     
    3941import org.hibernate.query.NativeQuery;
    4042import org.hibernate.query.QueryParameter;
     43import org.hibernate.query.internal.AbstractProducedQuery;
     44import org.hibernate.query.internal.QueryParameterBindingsImpl;
     45import org.hibernate.query.spi.QueryParameterBinding;
    4146import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
    4247import org.hibernate.type.Type;
     
    6267  }
    6368
     69  /**
     70    Get the underlying parent query from Hibernate.
     71  */
     72  public NativeQuery<R> getParentQuery()
     73  {
     74    return query;
     75  }
     76 
    6477  @Override
    6578  @Deprecated
     
    498511  }
    499512 
     513 
     514  // Reference to the "QueryParameterBindingsImpl.parameterBindingMap" variable
     515  private Field parameterBindingMap;
     516 
     517  /**
     518    We need to remove "synthetic" parameters from the "parameterBindingMap".
     519    The parameters are created by Hibernate when a list-type parameter is
     520    specified on a query: name_0, name_1, etc. The problem is that the
     521    "synthetic" parameters are never cleared and if the same query is re-used
     522    with a shorter list, Hibernate will try to set the non-existing parameters
     523    which causes an exception. See http://base.thep.lu.se/ticket/2110
     524  */
     525  @SuppressWarnings({ "unchecked", "rawtypes" })
    500526  private void clearOldParameterListParameters(String parameterName)
    501   {}
     527  {
     528    try
     529    {
     530      if (parameterBindingMap == null)
     531      {
     532        parameterBindingMap = QueryParameterBindingsImpl.class.getDeclaredField("parameterBindingMap");
     533        parameterBindingMap.setAccessible(true);
     534      }
     535     
     536      String prefixOfParametersToRemove = parameterName + "_";
     537      Map<QueryParameter<?>, QueryParameterBinding<?>> m = (Map)parameterBindingMap.get(((AbstractProducedQuery)query).getQueryParameterBindings());
     538      Iterator<QueryParameter<?>> i = m.keySet().iterator();
     539      while (i.hasNext())
     540      {
     541        String name = i.next().getName();
     542        if (name.startsWith(prefixOfParametersToRemove))
     543        {
     544          i.remove();
     545        }
     546      }
     547    }
     548    catch (Exception ex)
     549    {
     550      throw new RuntimeException(ex);
     551    }
     552  }
    502553}
Note: See TracChangeset for help on using the changeset viewer.