问题 更新后,Spring MVC将无法显示正确的数据库值


在我的控制器中,输入一个值 MySQL 数据库变成了 ModelAndView object 

有一个单独的程序更新表和 MVC 应该抓住该值,因此没有表格来更新该表。

当。。。的时候 表已更新,当我 在浏览器上点击刷新,值不会在页面上更新。

调节器

@SuppressWarnings("unchecked")
@Secured({ "ROLE_USER", "ROLE_ADMIN" })
@RequestMapping(value = { "/", "/welcome" }, method = RequestMethod.GET)
public ModelAndView defaultPage(@ModelAttribute("user") User user) {
    Collection<SimpleGrantedAuthority> authorities = (Collection<SimpleGrantedAuthority>) SecurityContextHolder
            .getContext().getAuthentication().getAuthorities();
    ModelAndView view = new ModelAndView("/hello");
    // Redirects to admin page if user has admin role
    if (authorities.toString().contains("ROLE_ADMIN")) {
        return new ModelAndView("redirect:/admin");
    }
    /////
    Authentication auth = SecurityContextHolder.getContext().getAuthentication();
    String userName = auth.getName();
    User userInfo = userDAO.getUserInfo(userName);
    System.out.println("Here's the thing " + userInfo.getLastname() + " " + userInfo.getUserDetails());
    Details details = userDAO.getDetailsInfo(userInfo.getUserDetails().getLastname(),
            userInfo.getUserDetails().getPostcode());
    Plugs plugs = userDAO.getPlugInfo(details.getMacAddress()); 
    String json = plugs.getJson();
    JSONObject obj = new JSONObject(json); //this is the value that is not updating
    String name = obj.getJSONObject("meta").getJSONObject("locate").getString("value");
    System.out.println(name); 
    view.addObject("json", obj);
    return view;
}

我知道这很受鄙视,但我把这个值放进去了 的JavaScript。

喜欢这个:

<c:set var="json" value="${json}"/> 

var __data__ = ${json};

为什么MVC在更新数据库时不会显示正确的值?

我希望它在刷新时更新

编辑:我已禁用缓存和清除缓存仍有问题。有帮助吗?


7036
2018-02-12 02:33


起源

对不起,不太清楚jsp重新加载你的意思 - bmarkham
是否有任何应用程序级缓存或二级缓存位于数据库前面的应用程序中? - Madhusudana Reddy Sunnapu
@MadhusudanaReddySunnapu我不完全确定 - bmarkham
如果您的应用中有任何缓存,这可能是您没有看到更新值的原因。你可能想检查一下。 - Madhusudana Reddy Sunnapu
我不确定缓存是否是问题。我的意思是它可能,但我清除缓存并设置标题,但它仍然没有显示正确的值。 - bmarkham


答案:


无疑 PersistenceContextType.EXTENDED 范围是您确定的问题的根本原因。原因如下:

PersistenceContextType.TRANSACTION 范围,Spring框架负责管理注入的生命周期 entitymanager。生命 TRANSACTION 范围与底层联系在一起 transaction 并且在提交/回滚事务时 entityManager 由弹簧框架关闭。

但随着 PersistenceContextType.EXTENDED 范围,Spring框架只负责注入 entitymanager。生命周期 EXTENDED 范围实体管理器与用户无关 transaction 它可以跨越多个交易。由应用程序/用户明确关闭 entityManager 一旦我们完成它。如果不是它将永远保持打开(或直到Spring容器关闭)。

我猜你的 userDAO 你还没关门 entityManager 明确。而且'userDAO'可能是一个单身人士。所以一样 entityManager 只注入一次的是多次调用(或http请求)

有了这个 entityManager' remains open forever and so when you try to access any object (User/Plugin/UserDetails) theentityManager`检查它的第一级缓存,它将检查它在其中找到的第一级缓存(第一次加载)并从第一级缓存(过时)返回此对象,而不是命中数据库。数据。

显然有 TRANSACTION 范围 entityManager 每当事务完成(或方法退出)时,Spring框架都会关闭它。这导致创建一个 entityManager 对于每个请求(在您的情况下是Web请求)命中具有更新数据的数据库。

看看这个链接是否有帮助。 http://forum.spring.io/forum/other-spring-related/ejb/18445-injection-of-persistencecontext-with-persistencecontexttype-extended


9
2018-02-15 07:17



哦,这是很棒的东西。谢谢。 - bmarkham


所以我的解决方案与我发布的代码无关,而是在我的UserDAO.java类中。

简单的改变。

由此:

@PersistenceContext(type = PersistenceContextType.EXTENDED)
private EntityManager em;

对此:

@PersistenceContext(type = PersistenceContextType.TRANSACTION)
private EntityManager em;

它的工作原理。感谢评论并试图帮助的人/

编辑:我讨厌回答我自己的问题,所以如果有人能够深入解释为什么这样做,我会接受它作为答案。


4
2018-02-15 06:00





http://docs.oracle.com/javaee/6/tutorial/doc/gkjio.html

禁用JPA二级缓存,否则实体管理器无法识别在数据库中直接更改的已更改数据 放

@Cacheable(false)

到你的实体


2
2018-02-17 13:12



我已经说过解决方案了,我也说过禁用任何缓存都行不通。 - bmarkham