java - Spring @Transactional 持久方法不起作用

标签 java spring

我有一个 Spring MVC 示例应用程序,它使用 UserDaoImpl 类将用户类型对象保存到数据库。以下是 UserDaoImpl 代码。

public class UserDaoImpl implements UserDao<User> {

private EntityManagerFactory emf;

@PersistenceContext
private EntityManager em;

@Transactional
public void saveUser(User user){
    em.persist(user);
}

我的 UserDao 界面是这样的。

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

当我的 UserDaoImpl 类实现 UserDao 接口(interface)时,发生了奇怪的事情。当尝试坚持时,它会出现以下错误。

java.lang.ClassCastException: $Proxy71 cannot be cast to org.samith.UserDaoImpl

当我从 UserDaoImpl 类中删除“implements UserDao”部分时,用户会按预期持久保存到数据库中。

我还尝试了没有 User 参数的 UserDao 接口(interface)(非通用版本)。仍然出现上述错误。

这可能是一个需要回答的微不足道的问题,但我花了大约几个小时挠头寻找解决方案。

我做错了什么??

最佳答案

您没有提供问题代码(或完整的堆栈跟踪),但概要是这样的:

当您将类注释为@Transactional 时,Spring 会为您创建一个实例,您得到的不是该类,而是实现该类接口(interface)的Java 动态代理。 http://download.oracle.com/javase/1.3/docs/guide/reflection/proxy.html

因此,您无法将该对象转换为原始类型(不再是该类型!),而必须改用它的接口(interface)。

如果没有要实现的接口(interface),它将为您提供该类的 CGLib 代理,它基本上只是您类的运行时修改版本,因此可分配给类本身。

搜索要注入(inject)的位置,或强制转换为类型 UserDaoImpl,然后更改对 UserDao 的引用,它将正常工作。

我读过 CGLib 代理和动态 Java 代理之间的性能差异非常小,因此您还可以将以下内容添加到您的 spring 配置中以强制它使用 CGLib 代理而不是 Java 动态代理:

<aop:config proxy-target-class="true">

不过,一般来说,我建议您不要使用 CGLib 代理,而是从类的界面访问您的类。松散耦合将允许您进行运行时替换,并限制您意外引入脆弱的类依赖性的能力。

然而,使用 Java 动态代理会引入一些问题,您所做的与我所做的非常接近,您应该意识到这一点:

How to use Dynamic Proxies with JSF when the method signature contains Object ... args

关于java - Spring @Transactional 持久方法不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7061872/

相关文章:

java - Weblogic 12c 上的 Spring 应用程序部署失败

java - 搞乱 JPA 并收到错误创建用户 - 无法设置字段值

java - 将十六进制字符串转换为整数

java - Gradle 尝试编译 jar 的源代码

java - 查看源代码与 Firebug 检查元素

java - 发生异常时 JBehave 不会导致构建失败

Java:将 Excel 中的数据存储在 ArrayList 的 ArrayList 中时出现问题

spring - Spring Boot 配置属性 Unresolved 占位符验证

java - Hibernate Artifact ID "hibernate-core",版本 4.3.5.Final 和 Artifact ID "hibernate",版本 3.2.3.ga

java - Spring + Hibernate Web 应用程序 - 何时使用缓存?