JPA合并不在ApplicationListener中工作,但在Controller中工作

时间:2015-04-22 07:50:11

标签: 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);
    }
}

userDAO的

@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);
    }
}

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

当我在控制器中执行以下操作时:

@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值。

问题是当成功登录发生时,即使我和控制器完全一样,数据库获取更新...我已确认实际调用了这些方法( onApplicationEventmerge)。

我绝对不知道为什么ApplicationListener中工作,但 在控制器中工作。我不能正确理解合并功能吗?

我阅读了以下内容:当您调用merge时,将返回一个托管实体,并且应该在数据库中更新对托管实体的更改,因此我还在userDao中尝试了以下内容: / p>

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

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

感谢阅读,希望你能帮忙! :)

1 个答案:

答案 0 :(得分:1)

通常,当事务在一种情况下不起作用而它们在另一种情况下工作时,您有多个组件实例。一个人已经应用了AOP而另一个没有。

这通常来自于<context:component-scan />ContextLoaderListener加载的上下文中的DispatcherServlet。在具有附加<tx:annotation-driven />的上下文中加载的那个将具有另一个不具有的工作事务。

您的ContextLoaderListener应该加载应用程序的全局bean(服务,daos,数据源等并应用了事务)。您的DispatcherServlet通常只应加载与Web相关的内容(控制器,查看解析器等)。