关于hibernate的奇怪查询问题

时间:2011-05-05 06:50:43

标签: mysql hibernate second-level-cache

我遇到了一个奇怪的问题,即更新&在hibernate中显示数据。任何人都可以帮助我!?

我正在使用hibernate,spring with mysql。

我面临的问题是,任何更改都可以应用于数据库。但是如果我在网页上加载更新的项目,它总是随机返回旧数据或新数据。

我确信这不是浏览器缓存的问题。我试图在dao类中的getPost方法中打印返回数据。它有时会打印出错误的信息。

说,如果我多次更改帖子内容,所有更改都可以存储在数据库中。但如果我不断刷新页面以显示更改的数据,它会随机显示所有先前的更改。

我尝试过不同的方法在getPost方法中加载数据,但仍面临同样的问题:

  1. 尝试了session.clear和session.flush

  2. 将二级缓存关闭为:

    <prop key="hibernate.cache.use_second_level_cache">false</prop>
    <prop key="hibernate.cache.use_query_cache">false</prop>
    <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
    <prop key="hibernate.cache.use_structured_entries">false</prop>
    
  3. 加载数据的不同方式:session.load,session.get,hibernate query,Criteria,都有相同的问题。

  4. 在postDAO的getPost方法中:我首先尝试通过本机SQL加载数据,并希望与hibernate查询的结果进行比较。两个查询都返回旧数据。

  5. 代码:

    public class Post implements Cloneable, Serializable {
    
        private String postID;
        private String content;
    }
    
    PostSelectController (controller):
    
    public class PostSelectController extends AbstractController
    {
    ....
    protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception
        {
            String id = request.getParameter("id");
    
            Course course = null;
            Vendor vendor = null;
            Post post = null;
    
            ModelAndView modelAndView = new ModelAndView();
    
            modelAndView.setViewName(getSuccessView());
    
            post = postService.getPost(id);
    
            modelAndView.addObject("post", post);
    
            return modelAndView;
        }
    }
    
    postService:
    
    @Transactional(propagation=Propagation.SUPPORTS, isolation=Isolation.READ_COMMITTED, readOnly=true)
    public class PostService
    {
    @Transactional(propagation=Propagation.REQUIRED, readOnly=false)
        public boolean updatePost(Post post) {
    
            System.out.println("service side::::::::::::::::::::::"+(post.getBestAnswer()!=null));
            if(post.getBestAnswer()!=null) System.out.println(">>>>>>>>"+post.getBestAnswer().getPostID());
            System.out.println("service side::::::::::::::::::::::"+(post.getBestAnswer()!=null));;
    
            return this.postDAO.updatePost(post);
        }
    
        public Post getPost(String postID) {
            return this.postDAO.getPost(postID);
        }
    }
    
    postDAO:
    
    public class  PostDAO {
    private SessionFactory sessionFactory;
    ...
    
    public boolean updatePost(Post post) {
            boolean proceed = true;
    
            try {
    
                Session session = sessionFactory.getCurrentSession();
                session.merge(post); //tried session.update, same problem
    
                session.flush(); //it does not help
    
            } catch (Exception ex) {
                logger.error(post.getPostID() + " refused :: " + ex.getMessage());
                proceed = false;
            }
            return proceed;
        }
    
    
    public Post getPost(String postID) {
    
            Session session = sessionFactory.getCurrentSession();       
            try{
             PreparedStatement st = session.connection()
                .prepareStatement("select content from post where postid='"+postID+"'") ;
    
                 ResultSet rs =st.executeQuery();
                 while (rs.next()) {
    
                    System.out.println("database::::::::::::::::::"+rs.getInt("content")); 
                    // tried to use native sql to load data from database and compare it with result of hibernate query.
                    break;
                 }
            }catch(Exception ex){
    
            }
    
            Criteria crit = session.createCriteria(Post.class);
            NaturalIdentifier natId = Restrictions.naturalId();
            natId.set("postID", postID);
            crit.add(natId);
            crit.setCacheable(false);
    
            List<Post> posts = crit.list();
    
            Post post = null;
            if(posts!=null)  post = posts.get(0);
            System.out.println("hibernate::::::::::::::::::"+post.getContent());
    
    
            return post;
    
        }
    

3 个答案:

答案 0 :(得分:1)

我遇到了同样的麻烦。答案我发现很快。正如里卡尔多所说,问题在于没有干净地关闭会议,因此会议被随机回收。我在班上的指导下完成了这个。

Ex(我在这里使用HybernateUtil):

 public yourHelper() {

        this.session = HibernateUtil.getSessionFactory().getCurrentSession();
         if (session.isOpen()){
            session.close();
            session=HibernateUtil.getSessionFactory().openSession();
        }   
    }

HibernateUtil的代码:

    public class HibernateUtil {

    private static final SessionFactory sessionFactory;

    static {
        try {
            // Create the SessionFactory from standard (hibernate.cfg.xml) 
            // config file.
            sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
            System.out.println("SRPU_INFO: Initial SessionFactory creation success.");
        } catch (Throwable ex) {
            // Log the exception.

            System.out.println("SRPU_INFO: Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
}

thanx for reading

答案 1 :(得分:0)

看起来您检索列表并仅显示列表的第一个条目。我猜这个列表中每个都有随机顺序填充多个项目,因为没有order-by条件。因此,不同执行的列表的第一个元素可能会有所不同。

您期待一个独特的结果吗?如果是这样,最好使用Criteria.uniqueResult();

答案 2 :(得分:0)

这可能取决于您获取会话的方式:如果您正在使用带有ThreadLocal会话的typycal HibernateUtil,则可能是您在使用完毕后未正确关闭会话的情况。在这种情况下,会话几乎随机地由完全不相关的工作单元循环,这将获得缓存值