This question already has an answer here:
NHibernate Get objects without proxy
(1 answer)
Closed 2 years ago.
Is there a way to make nhibernate return my class instead of its proxy class? I dont mind if it's not lazy or cant be updated.
You can unproxy class with this code
session.PersistenceContext.Unproxy(proxiedInstance)
You should define this in your mapping, by defining lazy="false"
<class name="MyEntity" table="MyTable" lazy="false">
</class>
You can use following code to get real object
InstanceType instance;
if (proxiedInstance is INHibernateProxy)
{
var lazyInitialiser = ((INHibernateProxy)proxiedInstance).HibernateLazyInitializer;
instance = (InstanceType)lazyInitialiser.GetImplementation();
}
I'm using AutoMapper to achieve something similar in Entity Framework.
var nonProxiedInstance = Mapper.DynamicMap<YourType>(proxiedInstance);
That would work if you do not have navigation properties. Otherwise, you'll need to configure a mapping to ignore those properties.
Note: This is (obviously) an inefficient solution.
You can use the technique described in http://sessionfactory.blogspot.com/2010/08/hacking-lazy-loaded-inheritance.html (you'll need to do it recursively)
session.PersistenceContext.Unproxy(proxiedInstance) will not unproxy the associations. Also the no-proxy lazy loading does the same thing.
Disabling lazy loading is not a good idea and AutoMapper would navigate all the properties and trigger the loading mechanism.
IUnitOfWork.Unproxy from the NHUnit package could be used to unproxy the object and it's relations. This method will not initialize any proxy objects by mistake.
Related
I ran into strange problem. I have the whole domain model defined in the orm.xml file. All my entities in my project are just simple POJOs (no jpa annotations at all). I want to save the last update and the insert timestamps of my entities and I've decided to use the "pre persist" and "pre update" like most of us. So I've defined a base entity class and let all my entities to extend it.
Strange is that the "pre persist" (and all others events) are being called only when I define them using annotations. When I define them in the orm.xml file instead - nothing happens, they are just ignored.
This works for me:
public abstract class BaseEntity {
private Timestamp insertTimestamp;
private Timestamp lastUpdateTimestamp;
#PrePersist
public void onPersist() {
...
}
#PreUpdate
public void onUpdate() {
...
}
}
But after removing annotations and switching to the xml nothing works anymore:
<mapped-superclass class="com.my.model.BaseEntity">
<pre-persist method-name="onPersist"/>
<pre-update method-name="onUpdate"/>
<post-load method-name="postLoad"/>
</mapped-superclass>
According to the JPA specification the above declarations in xml seem to be correct.
I have no idea where to dig for the problem.
I'm using EclipseLink 2.2.0 with H2 in the SE environment.
UPDATE:
Thanks for your answer. There are no errors in log/console to see. Events just seem being ignored.
As you thought is might be a bug because moving the methods and XML declarations from the superclass to the subclass solves the problem. It is not a desired solution for me as I want to have a global solution for all entities but moved me a bit forward.
I've sent the bug report to the EclipseLink guys :)
As you suggested I've tried with entity listener and it works for me. so I will stick to this solution. It even looks better then the solution with base entity class ;)
Thanks !
Your XML looks correct. Do any errors occur in the logs?
It could be a bug with MappedSuperClass and entity events.
Can you try setting the event on a subclass and see if it works?
If it does, then it is probably a bug, please log the bug in Eclipse Bugzilla.
Another workaround would be to use an entity listener.
I'm trying to make Fluent NHibernate's automapping ignore a Dictionary property on one of my classes, but Fluent is ignoring me instead. Ignoring other types of properties seems to work fine, but even after following the documentation and adding an override for the Dictionary, I still get the following exception when BuildSessionFactory is called:
The type or method has 2 generic parameter(s), but 1 generic argument(s) were provided. A generic argument must be provided for each generic parameter.
I've tried overriding by property name:
.Override<MyClass>(map => {
map.IgnoreProperty(x => x.MyDictionaryProperty);
})
and also tried implementing ignores using a custom attribute, both of which result in the same exception from BuildSessionFactory. The only thing so far that makes this exception go away is removing the Dictionary property entirely.
My question seems to be identical to this one which was never answered (though I'll expand the scope by stating it doesn't matter whether the dictionary is on an abstract base class; the problem always happens for me regardless of what class the property is on). Any takers this time around?
If you update to the latest version of Fluent NHibernate, IDictionarys are explicitly ignored automatically for this exact reason. This will remain the case until we can actually support them.
I am building a framework where people will be able to save items that the created by inheriting a class of mine. I will be iterating over every type in the appdomain to find classes that I want to map to nhibernate. Every class that I find will be a subclass of the inherited type.
I know how to create sub types in FluentNhibernate, but every sub type requires its own ClassMap class. Since I won't know these untill runtime, there is no way I can do that.
Is there a way that I can add mappings to fluent nhibernate?
Note, I know this is possible without fluent nhibernate using the Cfg class, but I don't want to manage the same code two different ways.
something along the lines
Type classToMap = GetClassToMap();
var subclassmap = typeof(SubClassMap<>).MakeGenericType(classToMap);
foreach(var item in classToMap.GetPropertiesToMapSomehow())
{
var expression = // build lambda of property
subclassMap.Map(expression).Column("col") ...
}
config.Add(subclassmap) // NHibernate.Cfg.Configuration
There was support for this at once time, and the api is still there, but it is now depricated.
I needed a way to trim strings within my persistent class because my legacy database is using char fields. I downloaded the nHhaddIns dll to use its TrimString class which is derived from IUserType.
Using their example I created a property in my mapping class as shown at the bottom.
uNHAddIns is added as a project within my solution. However, I received this error:"Could not determine type for: uNhAddIns.UserTypes.TrimString, uNhAddIns, for columns: NHibernate.Mapping.Column(HSTAT)"
I tried running the example that is in the uNhAddIns project and receive the same error. Any ideas?
<property name="HSTAT" column="HSTAT" type="uNhAddIns.UserTypes.TrimString, uNhAddIns" />
Don't know if you've managed to fix this already, but does your own uNhAddIns.UserTypes.TrimString inherit from IUserType? My own pattern for user types in NHibernate involves the type implementation living in the DataModel, and the required IUserType interface living separately in my DataAccess layer. The IUserType implementation does the necessary marshalling between the database and my DataModel type implementation.
I just came across this same error when trying to use the DataModel class in my mapping file rather than the IUserType implementation.
I have an class for auditing:
public class AuditAfterAdvise : IAfterReturningAdvice
This is applied to a Dao class in my Spring.Net configuration, using a RegularExpressionMethodPointcutAdvisor.
The Dao class implementation calls HibernateTemplate.SaveOrUpdate(object entity) to commit changes.
I would like to be able to apply AuditAfterAdvise class to the HibernateTemplate SaveOrUpdate() method used in my Dao, rather than the methods on the Dao itself.
The NHibenate/Spring setup is to use a LocalSessionFactoryObject for the Dao. Is this possible?
Thanks.
It certainly should be possible.
Instead of configuring the Dao, add the advice to the object definition for the LocalSessionFactoryObject. The RegularExpressionPointCutAdvisor should continue to work -- just applied to a different object.
I'm assuming the HibernateTemplate is retrieved from a Spring.NET object factory...