Spring @Transactional persist method not working
I have a Spring MVC sample application it uses UserDaoImpl class to save a User type object to database. Following is the UserDaoImpl code.
public class UserDaoImpl implements UserDao<User> {
private EntityManagerFactory emf;
@PersistenceContext
private EntityManager em;
@Transactional
public void saveUser(User user){
em.persist(user);
}
}
and my UserDao interface looks like this.
public interface UserDao<User> {
public void saveUser(User user);
}
Weird thing is happening when when my UserDaoImpl class implements the UserDao interface. When trying to persist it gives the following 开发者_如何学编程error.
java.lang.ClassCastException: $Proxy71 cannot be cast to org.samith.UserDaoImpl
When I remove the "implements UserDao" part from the UserDaoImpl class user is persisted to database as expected.
Also I tried UserDao interface without User parameter(that is non generic version). Still above error occurs.
This may be a trivial question to answer but I am scratching my head finding a solution for about few hours.
What wrong am I doing ??
You're not providing the problem code, (or the full stack trace) but the rundown is this:
When you annotate a class as @Transactional, and Spring creates an instance for you, what you get is not that class, but a Java Dynamic Proxy that implements that classes' interfaces. http://download.oracle.com/javase/1.3/docs/guide/reflection/proxy.html
Because of this, you cannot cast that object to the original type (it's not that type anymore!) and must use it's interface(s) instead.
If there aren't interfaces to implement, it will give you a CGLib proxy of the class, which is basically just a runtime modified version of your class, and so is assignable to the class itself.
Search for where you're injecting, or casting to type UserDaoImpl, and change the reference to UserDao instead, and it will work properly.
I've read the performance difference between CGLib proxies and Dynamic Java Proxies is quite minimal, so you can also add the following to your spring config to force it to use CGLib proxies instead of Java Dynamic Proxies:
<aop:config proxy-target-class="true">
In general however, I'd recommend you not use CGLib Proxies, but instead access your class from its interface. Loose coupling will allow you to do runtime substitution, and limits your ability to accidentally introduce brittle class dependencies.
There are some problems that using Java Dynamic Proxies will introduce however, and what you're doing is close enough to what I was doing that you should be aware of this:
How to use Dynamic Proxies with JSF when the method signature contains Object ... args
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
worked for me too. the point was proxy-target-class="true"
thanks to owner of the accepted answer. But then cglib dependency will be needed.
精彩评论