java - JPA 合并在 ApplicationListener 中不起作用,但在 Controller 中起作用

标签 java spring hibernate jpa

我的 JPA 合并功能遇到一些奇怪的问题。我正在尝试获取用户的上次登录时间,并且希望在用户登录时更新数据库中的用户。

成功登录事件的应用程序监听器:

@Component
public class SuccessLoginApplicationListener implements ApplicationListener<AuthenticationSuccessEvent>{
    @Autowired
    private UserDao userDao;

    @Override
    public void onApplicationEvent(AuthenticationSuccessEvent loginEvent) {
        User user = (User) loginEvent.getAuthentication().getPrincipal();
        user.setLastLogin(100000);
        userDao.merge(user);
    }
}

用户Dao

@Transactional
@Repository("userDao")
public class UserDao{
    protected EntityManager em;

    @PersistenceContext
    public void setEntityManager(EntityManager em) {
        this.em = em;
    }

    public User merge(User user){
        return em.merge(user);
    }
}

因为实际的代码包括一堆接口(interface)、其他方法等,所以上面的代码应该包括与这个问题相关的所有重要内容,我希望我没有忘记一些东西。

当我在 Controller 中执行以下操作时:

@Controller
@RequestMapping("/profile")
public class ProfileController {
    @Autowired
    private UserDao userDao;

    @RequestMapping(value="", method=RequestMethod.GET)
    public String profile(Model model){
        User user = getCurrentlyLoggedInUser();
        user.setLastLogin(1000000);
        userDao.merge(user);
        return "account/profile";
    }
}

一切都按照我的预期进行,数据库成功更改为新的lastLogin 值。

问题是,当成功登录时,即使我执行与 Controller 中完全相同的操作,数据库也不会获取更新...我已经确认这些方法实际上被调用了( onApplicationEvent合并)。

我完全不知道为什么它在 ApplicationListener不起作用,但它在 Controller 中起作用。我是否没有正确理解合并功能?

我读到了以下内容:当您调用合并时,会返回一个托管实体,并且对托管实体的更改应该会在数据库中更新,因此我还在 userDao 中尝试了以下操作:

public User merge(User user){
    User user = em.merge(user);
    user.setLastLogin(100000);
}

这里也发生同样的事情,当从 ApplicationListener 调用合并函数时,数据库中没有任何更改,但是当从 Controller 调用它时,该字段被正确设置为 100000。

感谢您的阅读,希望对您有所帮助! :)

最佳答案

一般来说,当事务在一种情况下不起作用而在另一种情况下起作用时,您就会拥有一个组件的多个实例。一个应用了 AOP,另一个没有应用。

这通常来自于具有相同的 <context:component-scan />ContextLoaderListener 加载的上下文中和DispatcherServlet 。在具有附加 <tx:annotation-driven /> 的上下文中加载的那个将进行有效交易,而其他则不会。

您的ContextLoaderListener应该加载应用程序全局的所有 bean(服务、daos、数据源等并应用了事务)。您的DispatcherServlet通常应该只加载与 Web 相关的东西( Controller 、 View 解析器等)。

关于java - JPA 合并在 ApplicationListener 中不起作用,但在 Controller 中起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29791047/

相关文章:

java - 在Java中如何匹配不是 "["的字符?

java - hadoop mapreduce : java. lang.UnsatisfiedLinkError : org. apache.hadoop.util.NativeCodeLoader.buildSupportsSnappy()Z

java - Reactor/WebFlux 实现了一个响应式的 http 新闻自动收报机

java - 使用 ObjectFactory 时 Mapstruct 无法映射属性

Spring JPARepository 查询多对多交集表

java - 将数学字符串转换为 int

java - Hibernate 左连接获取许多返回的口是心非

java - 多个 Spring Controller 是否应该指向同一个 View 文件?

java - 如何在 hibernate 中记录失败的sql?

java - 单个项目中的 Spring Hibernate 和 JDBC 模板