我的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值。
问题是当成功登录发生时,即使我和控制器完全一样,数据库不获取更新...我已确认实际调用了这些方法( onApplicationEvent
,merge
)。
我绝对不知道为什么不在ApplicationListener
中工作,但 在控制器中工作。我不能正确理解合并功能吗?
我阅读了以下内容:当您调用merge时,将返回一个托管实体,并且应该在数据库中更新对托管实体的更改,因此我还在userDao
中尝试了以下内容: / p>
public User merge(User user){
User user = em.merge(user);
user.setLastLogin(100000);
}
同样的事情发生在这里,当从ApplicationListener调用merge函数时,数据库中没有任何更改,但是当从Controller调用它时,该字段被正确设置为100000。
感谢阅读,希望你能帮忙! :)
答案 0 :(得分:1)
通常,当事务在一种情况下不起作用而它们在另一种情况下工作时,您有多个组件实例。一个人已经应用了AOP而另一个没有。
这通常来自于<context:component-scan />
和ContextLoaderListener
加载的上下文中的DispatcherServlet
。在具有附加<tx:annotation-driven />
的上下文中加载的那个将具有另一个不具有的工作事务。
您的ContextLoaderListener
应该加载应用程序的全局bean(服务,daos,数据源等并应用了事务)。您的DispatcherServlet
通常只应加载与Web相关的内容(控制器,查看解析器等)。