dressina
07-17-2007, 08:33 PM
Hello,
We recently upgraded to NHibernate 1.2-GA and Spring.NET 1.1 M1 and are now having some very confusing issues related to the query cache and NHibernate proxies... but mostly for only 1 class. The issues are sporadic. Nothing has changed with respect to this class during the upgrade.
Since the upgrade, we are now using: OpenSessionInViewModule for session management and the TransactionProxyFactoryObject in our business layer for transaction management. We are not using the HibernateTemplate 100%, as our legacy code requires a lot of work to get it there. However, we have hooked into the HibernateTemplate to give that legacy code access to the ISession (see below).
The issue surfaces when we pass a list of "Property" objects into a query. Property is lazy and the query is cached (see below). We believe it has something to do with a proxy in the query cache and some sort of SessionImpl issue.
Firstly, the stack trace of the issue (we have dealt with the *usual* lazy loading issues before and do not believe this is one of them):
"Could not initialize proxy - the owning Session was closed
" at NHibernate.Proxy.LazyInitializer.Initialize()\r\n at NHibernate.Proxy.CastleLazyInitializer.Intercept(I Invocation invocation, Object[] args)\r\n at CProxyTypeCore_DomainPropertyDomain_NHibernate_Pro xyINHibernateProxy_System_Runtime_SerializationISe rializable2.Equals(Object
obj)\r\n at System.Object.Equals(Object objA, Object objB)\r\n at NHibernate.Engine.TypedValue.Equals(Object obj)\r\n at System.Object.Equals(Object objA, Object objB)\r\n at NHibernate.Util.CollectionHelper.DictionaryEquals( IDictionary a, IDictionary b)\r\n at NHibernate.Cache.QueryKey.Equals(Object other)\r\n at NHibernate.Caches.SysCache.SysCache.Get(Object key)\r\n at NHibernate.Cache.StandardQueryCache.Get(QueryKey key, ICacheAssembler[] returnTypes, ISet spaces, ISessionImplementor session)\r\n at NHibernate.Loader.Loader.GetResultFromQueryCache(I SessionImplementor
session, QueryParameters queryParameters, ISet querySpaces, IType[] resultTypes, IQueryCache queryCache, QueryKey key)\r\n at NHibernate.Loader.Loader.ListUsingQueryCache(ISess ionImplementor
session, QueryParameters queryParameters, ISet querySpaces, IType[] resultTypes)\r\n at NHibernate.Loader.Loader.List(ISessionImplementor
session, QueryParameters queryParameters, ISet querySpaces, IType[] resultTypes)\r\n at NHibernate.Hql.Classic.QueryTranslator.List(ISessi onImplementor session, QueryParameters queryParameters)\r\n at NHibernate.Impl.SessionImpl.Find(String query, QueryParameters parameters, IList results)\r\n at NHibernate.Impl.SessionImpl.Find(String query, QueryParameters parameters)\r\n at NHibernate.Impl.QueryImpl.List()\r\n at
Proc.DataAccess.NHib.NHibernateProcurementDao.GetO penTransactionHeaderPage(Int32
recordIndex, Int32 pageSize, TransactionHeaderFields sortField, Boolean isDescending, TransactionType TrType, IList StatusList, IList
PropertyList) in
F:\\work\\\\Proc.DataAccess\\NHibernate\\NHibernat eProcDao.cs:line
5115" string
Our Spring / NHibernate Configs are:
<!-- Transactional Proxies For All Business Managers -->
<object id="TxProxyConfigurationTemplate" abstract="true"
type="Spring.Transaction.Interceptor.TransactionProxyFac toryObject, Spring.Data">
<property name="PlatformTransactionManager" ref="HibernateTransactionManager"/>
<property name="TransactionAttributes">
<name-values>
<!-- Add common methods across your services here -->
<add key="Update*" value="PROPAGATION_REQUIRED"/>
<add key="Delete*" value="PROPAGATION_REQUIRED"/>
<add key="Create*" value="PROPAGATION_REQUIRED"/>
<add key="Get*" value="PROPAGATION_REQUIRED,readOnly"/>
<add key="Find*" value="PROPAGATION_REQUIRED,readOnly"/>
</name-values>
</property>
</object>
<!-- Database and NHibernate Configuration -->
<db:dbProvider id="DbProvider" provider="System.Data.SqlClient"
connectionString="Data Source=${db.datasource};Initial Catalog=${db.database};Integrated Security=${db.integrated_security};Persist Security Info=false;Min Pool Size=2"/>
<object id="SessionFactory" type="Core.DataAccess.NHib.SammsLocalSessionFactoryObjec t, Tradewinds.Samms.Core.DataAccess">
<property name="DbProvider" ref="DbProvider"/>
<property name="MappingAssemblies">
<list>
<value>Core.DataAccess</value>
<value>Inventory.DataAccess</value>
</list>
</property>
<property name="HibernateProperties">
<dictionary>
<entry key="hibernate.connection.provider"
value="NHibernate.Connection.DriverConnectionProvider"/>
<entry key="hibernate.dialect"
value="NHibernate.Dialect.MsSql2005Dialect"/>
<entry key="hibernate.connection.driver_class"
value="NHibernate.Driver.SqlClientDriver"/>
<entry key="hibernate.use_outer_join"
value="true"/>
<entry key="hibernate.cache.use_query_cache"
value="true"/>
<entry key="hibernate.cache.provider_class"
value="NHibernate.Caches.SysCache.SysCacheProvider,NHiber nate.Caches.SysCache"/>
<entry key="expiration"
value="300"/>
<entry key="hibernate.bytecode.provider"
value="lcg"/>
</dictionary>
</property>
<property name="EntityInterceptor" ref="RevisionUpdateInterceptor" />
</object>
<object id="HibernateTransactionManager"
type="Spring.Data.NHibernate.HibernateTransactionManager , Spring.Data.NHibernate12">
<property name="DbProvider" ref="DbProvider"/>
<property name="SessionFactory" ref="SessionFactory"/>
<property name="EntityInterceptor" ref="RevisionUpdateInterceptor" />
</object>
<object id="HibernateTemplate" type="Spring.Data.NHibernate.Generic.HibernateTemplate">
<property name="SessionFactory" ref="SessionFactory" />
<property name="TemplateFlushMode" value="Auto" />
<property name="CacheQueries" value="true" />
<property name="EntityInterceptor" ref="RevisionUpdateInterceptor" />
</object>
Property Mapping file:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="Core.Domain.Property, Core.Domain" table="PROPERTY">
<cache usage="read-write"/>
<id name="Id" type="Int32" unsaved-value="0">
<column name="PRP_ID" sql-type="int" not-null="true" unique="true" index="PK_PROPERTY"/>
<generator class="native" />
</id>
<property name="Code" type="String">
<column name="PRP_CODE" length="20" sql-type="nvarchar" not-null="true"/>
</property>
</class>
</hibernate-mapping>
And the DAO Code:
public IPage GetFilteredOpenTransactionHeaderPage(int recordIndex,
int pageSize,
TransactionHeaderFields sortField,
bool isDescending,
TransactionType TrType,
IList StatusList,
IList PropertyList,
ProcHeader criteria,
string reqDateSeachType,
string createDateSeachType)
{
IPage page = null;
IList records = null;
ISession session = null;
IQuery recordQuery = null;
...
session = PersistenceManager.OpenSession();
...
// This is the list of properties that is involved in the exception
recordQuery.SetParameterList("propList", PropertyList);
...
recordQuery.SetParameter("transType", TrType);
...
// This causes the exception
records = recordQuery.SetFirstResult(recordIndex)
.SetMaxResults(pageSize + 1)
.SetCacheable(true)
.SetCacheRegion(CacheRegions.CACHE_REGION_TRANSACT IONS)
.List();
return page;
}
PersistenceManager is our hook into the HibernateTemplate:
public sealed class PersistenceManager
{
private ISessionFactory sessionFactory;
public PersistenceManager(ISessionFactory sessionFactory)
{
this.sessionFactory = sessionFactory;
}
public ISession OpenSession()
{
return SessionFactoryUtils.GetSession(sessionFactory, true);
}
}
where SessionFactory is:
return new PersistenceManager(hibernateTemplate.SessionFactor y);
Thank you very much in advance,
Aaron
We recently upgraded to NHibernate 1.2-GA and Spring.NET 1.1 M1 and are now having some very confusing issues related to the query cache and NHibernate proxies... but mostly for only 1 class. The issues are sporadic. Nothing has changed with respect to this class during the upgrade.
Since the upgrade, we are now using: OpenSessionInViewModule for session management and the TransactionProxyFactoryObject in our business layer for transaction management. We are not using the HibernateTemplate 100%, as our legacy code requires a lot of work to get it there. However, we have hooked into the HibernateTemplate to give that legacy code access to the ISession (see below).
The issue surfaces when we pass a list of "Property" objects into a query. Property is lazy and the query is cached (see below). We believe it has something to do with a proxy in the query cache and some sort of SessionImpl issue.
Firstly, the stack trace of the issue (we have dealt with the *usual* lazy loading issues before and do not believe this is one of them):
"Could not initialize proxy - the owning Session was closed
" at NHibernate.Proxy.LazyInitializer.Initialize()\r\n at NHibernate.Proxy.CastleLazyInitializer.Intercept(I Invocation invocation, Object[] args)\r\n at CProxyTypeCore_DomainPropertyDomain_NHibernate_Pro xyINHibernateProxy_System_Runtime_SerializationISe rializable2.Equals(Object
obj)\r\n at System.Object.Equals(Object objA, Object objB)\r\n at NHibernate.Engine.TypedValue.Equals(Object obj)\r\n at System.Object.Equals(Object objA, Object objB)\r\n at NHibernate.Util.CollectionHelper.DictionaryEquals( IDictionary a, IDictionary b)\r\n at NHibernate.Cache.QueryKey.Equals(Object other)\r\n at NHibernate.Caches.SysCache.SysCache.Get(Object key)\r\n at NHibernate.Cache.StandardQueryCache.Get(QueryKey key, ICacheAssembler[] returnTypes, ISet spaces, ISessionImplementor session)\r\n at NHibernate.Loader.Loader.GetResultFromQueryCache(I SessionImplementor
session, QueryParameters queryParameters, ISet querySpaces, IType[] resultTypes, IQueryCache queryCache, QueryKey key)\r\n at NHibernate.Loader.Loader.ListUsingQueryCache(ISess ionImplementor
session, QueryParameters queryParameters, ISet querySpaces, IType[] resultTypes)\r\n at NHibernate.Loader.Loader.List(ISessionImplementor
session, QueryParameters queryParameters, ISet querySpaces, IType[] resultTypes)\r\n at NHibernate.Hql.Classic.QueryTranslator.List(ISessi onImplementor session, QueryParameters queryParameters)\r\n at NHibernate.Impl.SessionImpl.Find(String query, QueryParameters parameters, IList results)\r\n at NHibernate.Impl.SessionImpl.Find(String query, QueryParameters parameters)\r\n at NHibernate.Impl.QueryImpl.List()\r\n at
Proc.DataAccess.NHib.NHibernateProcurementDao.GetO penTransactionHeaderPage(Int32
recordIndex, Int32 pageSize, TransactionHeaderFields sortField, Boolean isDescending, TransactionType TrType, IList StatusList, IList
PropertyList) in
F:\\work\\\\Proc.DataAccess\\NHibernate\\NHibernat eProcDao.cs:line
5115" string
Our Spring / NHibernate Configs are:
<!-- Transactional Proxies For All Business Managers -->
<object id="TxProxyConfigurationTemplate" abstract="true"
type="Spring.Transaction.Interceptor.TransactionProxyFac toryObject, Spring.Data">
<property name="PlatformTransactionManager" ref="HibernateTransactionManager"/>
<property name="TransactionAttributes">
<name-values>
<!-- Add common methods across your services here -->
<add key="Update*" value="PROPAGATION_REQUIRED"/>
<add key="Delete*" value="PROPAGATION_REQUIRED"/>
<add key="Create*" value="PROPAGATION_REQUIRED"/>
<add key="Get*" value="PROPAGATION_REQUIRED,readOnly"/>
<add key="Find*" value="PROPAGATION_REQUIRED,readOnly"/>
</name-values>
</property>
</object>
<!-- Database and NHibernate Configuration -->
<db:dbProvider id="DbProvider" provider="System.Data.SqlClient"
connectionString="Data Source=${db.datasource};Initial Catalog=${db.database};Integrated Security=${db.integrated_security};Persist Security Info=false;Min Pool Size=2"/>
<object id="SessionFactory" type="Core.DataAccess.NHib.SammsLocalSessionFactoryObjec t, Tradewinds.Samms.Core.DataAccess">
<property name="DbProvider" ref="DbProvider"/>
<property name="MappingAssemblies">
<list>
<value>Core.DataAccess</value>
<value>Inventory.DataAccess</value>
</list>
</property>
<property name="HibernateProperties">
<dictionary>
<entry key="hibernate.connection.provider"
value="NHibernate.Connection.DriverConnectionProvider"/>
<entry key="hibernate.dialect"
value="NHibernate.Dialect.MsSql2005Dialect"/>
<entry key="hibernate.connection.driver_class"
value="NHibernate.Driver.SqlClientDriver"/>
<entry key="hibernate.use_outer_join"
value="true"/>
<entry key="hibernate.cache.use_query_cache"
value="true"/>
<entry key="hibernate.cache.provider_class"
value="NHibernate.Caches.SysCache.SysCacheProvider,NHiber nate.Caches.SysCache"/>
<entry key="expiration"
value="300"/>
<entry key="hibernate.bytecode.provider"
value="lcg"/>
</dictionary>
</property>
<property name="EntityInterceptor" ref="RevisionUpdateInterceptor" />
</object>
<object id="HibernateTransactionManager"
type="Spring.Data.NHibernate.HibernateTransactionManager , Spring.Data.NHibernate12">
<property name="DbProvider" ref="DbProvider"/>
<property name="SessionFactory" ref="SessionFactory"/>
<property name="EntityInterceptor" ref="RevisionUpdateInterceptor" />
</object>
<object id="HibernateTemplate" type="Spring.Data.NHibernate.Generic.HibernateTemplate">
<property name="SessionFactory" ref="SessionFactory" />
<property name="TemplateFlushMode" value="Auto" />
<property name="CacheQueries" value="true" />
<property name="EntityInterceptor" ref="RevisionUpdateInterceptor" />
</object>
Property Mapping file:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="Core.Domain.Property, Core.Domain" table="PROPERTY">
<cache usage="read-write"/>
<id name="Id" type="Int32" unsaved-value="0">
<column name="PRP_ID" sql-type="int" not-null="true" unique="true" index="PK_PROPERTY"/>
<generator class="native" />
</id>
<property name="Code" type="String">
<column name="PRP_CODE" length="20" sql-type="nvarchar" not-null="true"/>
</property>
</class>
</hibernate-mapping>
And the DAO Code:
public IPage GetFilteredOpenTransactionHeaderPage(int recordIndex,
int pageSize,
TransactionHeaderFields sortField,
bool isDescending,
TransactionType TrType,
IList StatusList,
IList PropertyList,
ProcHeader criteria,
string reqDateSeachType,
string createDateSeachType)
{
IPage page = null;
IList records = null;
ISession session = null;
IQuery recordQuery = null;
...
session = PersistenceManager.OpenSession();
...
// This is the list of properties that is involved in the exception
recordQuery.SetParameterList("propList", PropertyList);
...
recordQuery.SetParameter("transType", TrType);
...
// This causes the exception
records = recordQuery.SetFirstResult(recordIndex)
.SetMaxResults(pageSize + 1)
.SetCacheable(true)
.SetCacheRegion(CacheRegions.CACHE_REGION_TRANSACT IONS)
.List();
return page;
}
PersistenceManager is our hook into the HibernateTemplate:
public sealed class PersistenceManager
{
private ISessionFactory sessionFactory;
public PersistenceManager(ISessionFactory sessionFactory)
{
this.sessionFactory = sessionFactory;
}
public ISession OpenSession()
{
return SessionFactoryUtils.GetSession(sessionFactory, true);
}
}
where SessionFactory is:
return new PersistenceManager(hibernateTemplate.SessionFactor y);
Thank you very much in advance,
Aaron