简体   繁体   English

Spring @Transactional persist 方法不起作用

[英]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.我有一个 Spring MVC 示例应用程序,它使用 UserDaoImpl class 将用户类型 object 保存到数据库。 Following is the UserDaoImpl code.以下是 UserDaoImpl 代码。

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.我的 UserDao 界面看起来像这样。

public interface UserDao<User> {
public void saveUser(User user);

} }

Weird thing is happening when when my UserDaoImpl class implements the UserDao interface.当我的 UserDaoImpl class 实现 UserDao 接口时,发生了奇怪的事情。 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.当我从 UserDaoImpl class 中删除“实现 UserDao”部分时,用户按预期保存到数据库。

Also I tried UserDao interface without User parameter(that is non generic version).我还尝试了没有 User 参数的 UserDao 接口(即非通用版本)。 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. 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 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.因此,您不能将 object 转换为原始类型(不再是那种类型。)并且必须改用它的接口。

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.如果没有要实现的接口,它将为您提供 class 的 CGLib 代理,它基本上只是 class 的运行时修改版本,因此可分配给 class 本身。

Search for where you're injecting, or casting to type UserDaoImpl, and change the reference to UserDao instead, and it will work properly.搜索您要注入的位置,或强制类型为 UserDaoImpl,然后更改对 UserDao 的引用,它会正常工作。

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: 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.但是,总的来说,我建议您不要使用 CGLib 代理,而是从其界面访问您的 class。 Loose coupling will allow you to do runtime substitution, and limits your ability to accidentally introduce brittle class dependencies.松耦合将允许您进行运行时替换,并限制您意外引入脆弱的 class 依赖项的能力。

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:但是,使用 Java 动态代理会引入一些问题,并且您所做的与我所做的足够接近,您应该注意这一点:

How to use Dynamic Proxies with JSF when the method signature contains Object... args 当方法签名包含 Object... args 时如何将动态代理与 JSF 一起使用

<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.感谢接受答案的所有者,关键是proxy-target-class="true" But then cglib dependency will be needed.但随后将需要 cglib 依赖项。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM