View Full Version : Support for Generics in HibernateTemplate?
nokiola
09-03-2006, 11:39 AM
Hello,
Are there any plans to introduce support for NHibernate 1.2 generics in HibernateTemplate? Load, Get, List and other methods have in NHibernate 1.2 native support for returning Generic types and collections.
Does Spring.NET support returning such generics collections?
Regards,
Robert
Mark Pollack
09-05-2006, 03:29 PM
Hi Robert,
I haven't looked into 1.2 yet but if having a HibernateTemplate adds value in terms of session/tx managements for 1.2, then yes, we will provide support for that. HibernateTemplate API wise should at heart be a simple 'mirror' of the session api.
Cheers,
Mark
sreenivask
11-10-2006, 06:16 PM
Hi Robert,
I haven't looked into 1.2 yet but if having a HibernateTemplate adds value in terms of session/tx managements for 1.2, then yes, we will provide support for that. HibernateTemplate API wise should at heart be a simple 'mirror' of the session api.
Hi Mark:
We are using 1.2 primarily because of its support for generics. We used the Nov 6, 2006 snapshot from CVS and subclassed HibernateTemplate for supporting generics. (I wonder if I am breaking anything; I will clean up the code and post it in a short while.) Unfortunately the latest changes in CVS repository break the build with 1.2. Here is the error:
Spring.Data.NHibernate\Data\NHibernate\SessionFact oryUtils.cs(571,56): error CS0117: 'NHibernate.Driver.IDriver' does not contain a definition for 'ConnectionType'
Is there another way of getting the assembly name in SessionFactoryUtils other than calling ConnectionType?
Thanks.
Sreenivas
I was actually doing the same thing today, when searching the nhibernate forum I found this reference (http://forum.hibernate.org/viewtopic.php?t=965717&highlight=idriver) to IDriver.
Perhaps change the line into this:
Type hibConnectionType = cp.Driver.CreateConnection().GetType();
might solve it but I'm not sure. It seems a bit overkill though.
harald
11-10-2006, 07:15 PM
I also subclassed HibernateTemplate to have generics support which is availabe at http://springutils.fluffnstuff.org/browser/trunk/SpringUtils/Data/NHibernate/Generics. The code is not yet NHibernate 1.2 specific which means it also works with NHibernate 1.0 but involves some casting (which might have a performance impact in some cases).
In the Java world a separate Hibernate3 namespace was introduced for the new Hibernate release (and in some aspects NHibernate 1.2 is more like Hibernate3 than Hibernate2), thus fully retaining backwards compatibility in the old namespace. maybe this is an option too?
sreenivask
11-10-2006, 09:50 PM
Harald:
I saw your utils code. It looked cleaner than my approach (neater than my code too!), but as you said there is a performance penalty. So I decided to stick with reimplimenting all the way through to the NHibernate calls.
I have some misgivings though: for example, there were some private methods and internal classes that I had to reimpliment in the subclass. I was not sure at all if am breaking something--I would need Mark's review.
I liked the subclassing approach as it would help in keeping .NET 2.0-specific code separate from .NET 1.1 code. Hoping to ultimately persuade Mark to providing support for generics ;-)
Sreenivask
Mark Pollack
11-10-2006, 09:53 PM
Hi,
Thanks for the feedback! I was starting to think that SessionFactoryUtils.GetDbProvider is of dubious value and get rid of it. Yea, I've very much like to avoid creating a connection. I'll take a look at the 1.2 API, maybe I can get at it via reflection and I'll also ping the NHibernate guys to see if they can open up their API a bit (also w.r.t to getting at the ado.net transaction object).
About the generic class - great stuff! I had started on the generic version of AdoTemplate (for the Query methods that take IRowMapper) and I had ran into problems having overloaded generic methods (same name) that had generic method arguments when the base class was not generic. (I think that was the case...) That lead me to believe that we might even need two different "operations" interfaces. The HibernateTemplate doesn't seem to suffer from this issue it seems. I'll mull it over a bit more - either way looks like we can use your code!
Cheers,
Mark
sreenivask
11-11-2006, 12:24 AM
Hi Mark:
Here is the code. I zipped up the project (created in SharpDevelop) but you will have to reset the assembly references.
The unit tests I have are based on our own functional tests and would need to be rewritten. If you want, I will be on that job over the weekend.
Regards.
Sreenivas
Mark Pollack
11-11-2006, 09:45 PM
Hi,
Thanks for the submissions, I'm going over them now and hope to commit some generic support this weekend.
Cheers,
Mark
sreenivask
11-12-2006, 12:48 PM
I had started on the generic version of AdoTemplate (for the Query methods that take IRowMapper) and I had ran into problems having overloaded generic methods (same name) that had generic method arguments when the base class was not generic. (I think that was the case...) That lead me to believe that we might even need two different "operations" interfaces. The HibernateTemplate doesn't seem to suffer from this issue it seems.
I too faced the same problems but I "avoided" the whole issue by ignoring the IHibernateOperations interface. I realize that this cheap short cut was ok for my project but not for you. Apologies for leaving so much work for a proper integration!
Mark Pollack
11-12-2006, 03:40 PM
Hi,
I worked on this last night, thanks for your contribution Sree! I am sorting out the design a bit. I think with code completion in the IDE extending IHibernateOperations with additional overload methods for generics will make the class to unwieldy to use. I recently renamed methods in AdoTemplate to avoid having more than 4-5 overloads per method.
My current plan is to move all shared methods into a common interface, with specific generic/non-generic IHibernateOperations sub-interfaces. The generic HibnerateTemplate will have a 'classic' non-generic 'ClassicHibernateTemplate' property if one needs to get at non-generic operations and also to delegate to for non-generic operations. (Composition). I see that the NH 1.2 just added the generic methods but they don't have as many overloads as we do. I also moved some 'classic' hibernate template methods into a new base class to share between both generic/non-generic implementations.
The bigger issue is logging - ug. NH 1.2 uses log4net 1.2.10 which has a different key used to sign the assembly as compared to 1.2.9. This means you can't use assembly redirect - they are two different products as far as .NET is concerned. As such, I'll be needing a logging abstraction, I'm looking into http://www.gotdotnet.com/Workspaces/Workspace.aspx?id=e5546f13-1ced-47d1-8667-53b613cc4873 as well as what IBatis has.
Cheers,
Mark
Mark Pollack
11-21-2006, 07:07 AM
Hi,
I've added to CVS support for NHibernate 1.2. You can find it under 'Spring.Net.Integration/projects/Spring.NHibernate12'. I've pushed more common functionality up into HibernateAccessor (the base class) and extracted a common operations interface. I delegate to an 'classic' hibernate template for all non-generic methods of Spring.Data.NHibernate.Generic.HibernateTemplate.
Try it out and let me know how it goes. Much thanks for your code contributions Sree.
Mark
BTW, you need to add the following for spring's logging configuration
<sectionGroup name="common">
<section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging" />
</sectionGroup>
<common>
<logging>
<factoryAdapter type="Common.Logging.Log4Net.Log4NetLoggerFactoryAdapter , Common.Logging.Log4Net">
<!-- choices are INLINE, FILE, FILE-WATCH, EXTERNAL-->
<!-- otherwise BasicConfigurer.Configure is used -->
<!-- log4net configuration file is specified with key configFile-->
<arg key="configType" value="EXTERNAL" />
</factoryAdapter>
</logging>
</common>
If you are using NHibernate 1.0.x then change the assembly to Common.Logging.Log4Net129.
sreenivask
11-22-2006, 12:39 AM
Hi Mark:
I have been eagerly waiting for this--checking the fisheye twice a day. Thanks!
Unfortunately faced some some hiccups in building the source.
[csc] Compiling 8 files to '\cvs-src\Spring.Net.Integration\projects\Spring.Data.NH ibernate12\build\net\2.0\debug\Spring.Data.NHibern ate12.dll'.
[csc] \cvs-src\Spring.Net.Integration\projects\Spring.Data.NH ibernate12\src\Spring\Spring.Data.NHibernate12\Dat a\NHibernate\Generic\HibernateTemplate.cs(67,38): error CS0246: The type or namespace name 'HibernateAccessor' could not be found (are you missing a using directive or an assembly reference?)
[csc] cvs-src\Spring.Net.Integration\projects\Spring.Data.NH ibernate12\src\Spring\Spring.Data.NHibernate12\Dat a\NHibernate\Generic\IHibernateOperations.cs(41,45 ): error CS0246: The type or namespace name 'ICommonHibernateOperations' could not be found (are you missing a using directive or an assembly reference?)
[csc] cvs-src\Spring.Net.Integration\projects\Spring.Data.NH ibernate12\src\Spring\Spring.Data.NHibernate12\Dat a\NHibernate\Generic\HibernateTemplate.cs(71,32): error CS0234: The type or namespace name 'HibernateTemplate' does not exist in the namespace 'Spring.Data.NHibernate' (are you missing an assembly reference?
Taking a hint from the .csproj file, I did the following changes to the build file "projects\Spring.Data.NHibernate12\src\Spring\Sprin g.Data.NHibernate12\Spring.Data.NHibernate12.build":
Added the following:
<include name="../../../../Spring.Data.NHibernate/src/**/*.cs" />
And commented out the following:
<!--include name="../CommonAssemblyInfo.cs" /-->
The main build file (Spring.Data.NHibernate/common/nant/Spring.build) insisted on building with Framework 1.1! I had to comment that out too! It worked for now. I am still investigating why it ignores the settings in "projects\Spring.Data.NHibernate12\Spring.Data.NHib ernate12.build" that specify this: <property name="compile-net-1.1" value="false"/>
And here are some XML comment-related warnings from compilation:
[csc] NHibernate\Generic\HibernateTemplate.cs(125,30): warning CS1591:
Missing XML comment for publicly visible type or member 'Spring.Data.NHibernate.Generic.HibernateTemplate. AfterSetSessionFactory(NHibernate.ISessionFactory) '
[csc] NHibernate\Generic\HibernateTemplate.cs(115,45): warning CS1591:
Missing XML comment for publicly visible type or member 'Spring.Data.NHibernate.Generic.HibernateTemplate. ClassicHibernateTemplate'
BTW, there is a spurious class (created by Visual Studio, perhaps) that needs to be deleted: projects\Spring.Data.NHibernate12\src\Spring\Sprin g.Data.NHibernate12\Class1.cs
Much thanks for your code contributions Sree
My code-contribution is confined to copy-pasting your code and adding angle brackets; and I really enjoyed the copy-paste ;)
I should be able to report any issues in the next few days, as quite a few of us (15, to be precise!) will be coding/testing with the generic support. That would be my true contribution. You can thank me then!
sreenivask
11-22-2006, 04:34 AM
Hi Mark:
Another issue. I got a Null Reference exception during initialization:
Error instantiating context 'spring.root'.
<snip>
System.NullReferenceException: Object reference not set to an instance of an object.
at Spring.Data.NHibernate.Generic.HibernateTemplate.A fterSetSessionFactory(ISessionFactory sessionFactory) in Spring.Net.Integration\projects\Spring.Data.NHiber nate12\src\Spring\Spring.Data.NHibernate12\Data\NH ibernate\Generic\HibernateTemplate.cs:line 127
at Spring.Data.NHibernate.HibernateAccessor.set_Sessi onFactory(ISessionFactory value) in Spring.Net.Integration\projects\Spring.Data.NHiber nate\src\Spring\Spring.Data.NHibernate\Data\NHiber nate\HibernateAccessor.cs:line 181
at Spring.Data.NHibernate.Generic.HibernateTemplate.. ctor(ISessionFactory sessionFactory) in Spring.Net.Integration\projects\Spring.Data.NHiber nate12\src\Spring\Spring.Data.NHibernate12\Data\NH ibernate\Generic\HibernateTemplate.cs:line 92
at Spring.Data.NHibernate.Generic.Support.HibernateDa oSupport.CreateHibernateTemplate(ISessionFactory sessionFactory)
in Spring.Net.Integration\projects\Spring.Data.NHiber nate12\src\Spring\Spring.Data.NHibernate12\Data\NH ibernate\Generic\HibernateDaoSupport.cs:line 122
at Spring.Data.NHibernate.Generic.Support.HibernateDa oSupport.set_SessionFactory(ISessionFactory value) in Spring.Net.Integration\projects\Spring.Data.NHiber nate12\src\Spring\Spring.Data.NHibernate12\Data\NH ibernate\Generic\HibernateDaoSupport.cs:line 104]
And I fixed it like this:
public override void AfterSetSessionFactory(ISessionFactory sessionFactory)
{
if (classicHibernateTemplate == null)
{
classicHibernateTemplate = new Spring.Data.NHibernate.HibernateTemplate();
}
classicHibernateTemplate.SessionFactory = sessionFactory;
}
Is it ok?
Mark Pollack
11-22-2006, 06:09 AM
Hi Sree,
I believe I fixed all the issues you mentioned. I didn't realize you were going to try and use nant to build - I knew that wasn't finished yet.
Not allowing for the creation of the 'classic' hibernate template in AfterSetSessionFactory was a bug - thanks for finding it. Looking forward to you battle testing the code.
Cheers,
Mark
sreenivask
12-01-2006, 05:31 PM
Hi Mark:
The current overloads for ExecuteFind<T> do not seem to accept anonymous methods. So, following the pattern in the overloads for Execute<T>, I created FindHibernateDelegate and used it to overload ExecuteFind<T>() like this:
public IList<T> ExecuteFind<T>(FindHibernateDelegate<T> del)
{
return ExecuteFind<T>(new ExecuteFindHibernateCallbackUsingDelegate<T>(del));
}
public IList<T> ExecuteFind<T>(FindHibernateDelegate<T> del, bool exposeNativeSession)
{
return ExecuteFind<T>(new ExecuteFindHibernateCallbackUsingDelegate<T>(del), true);
}
public IList<T> ExecuteFind<T>(IFindHibernateCallback<T> action)
{
return ExecuteFind<T>(action, ExposeNativeSession);
}
The following sample code works now:
IList<Supplier> suppliers = HibernateTemplate.ExecuteFind<Supplier>(
delegate(ISession session)
{
return session.CreateQuery("from Supplier s were s.Code = ?")
.SetParameter(0, code)
.List<Supplier>();
});
Regards.
PS: The combination of the three musketeers--TransactionTemplate, AdoTemplate and HibernateTemplate--is deadly, I must admit!
Mark Pollack
12-14-2006, 08:34 PM
Hi Sree,
Thanks once again. I'll get this incorporated soon.
Mark
the_bmo
02-08-2007, 02:04 PM
Don't forger to incorporat it ;)
the_bmo
02-16-2007, 09:16 AM
up please ;)
nokiola
03-05-2007, 09:08 PM
Hi Mark,
Could you please patch HibernateTemplate with sreenivask patch so that ExecuteFind<T> would accept anonymous methods? Our DAO code looks much cleaner with this patch applied.
Regards,
Robert
Mark Pollack
03-05-2007, 09:27 PM
Hi,
I've added it (now ) but CVS seems to be down. I'll ping back once it is in there and you can get a new download.
Cheers,
Mark
Mark Pollack
03-06-2007, 04:46 PM
Hi,
Ok, you can now get the latest from the module download page that includes these changes.
Cheers,
Mark
the_bmo
03-07-2007, 08:22 AM
Thx our code will be more clean.
vBulletin® v3.7.3, Copyright ©2000-2008, Jelsoft Enterprises Ltd.