Странная проблема с запросом в режиме гибернации

#mysql #hibernate #second-level-cache

#mysql #режим гибернации #кэш второго уровня

Вопрос:

Я столкнулся со странной проблемой с обновлением и отображением данных в режиме гибернации. Кто-нибудь может мне помочь, пожалуйста!?

Я использую hibernate, spring с mysql.

Проблема, с которой я сталкиваюсь, заключается в том, что любые изменения могут быть применены к базе данных. Но если я загружаю обновленный элемент на веб-страницу, он всегда возвращает старые данные или новые данные случайным образом.

Я уверен, что это не проблема кэша браузера. Я попытался распечатать возвращаемые данные в методе getPost в классе dao. Иногда он просто выводит неправильное сообщение.

Скажем, если я изменяю содержимое публикации несколько раз, все изменения могут быть сохранены в базе данных. Но если я постоянно обновляю страницу для отображения измененных данных, она отображает все предыдущие изменения случайным образом.

Я пробовал разные способы загрузки данных в метод getPost, но все еще сталкиваюсь с той же проблемой:

  1. пробовал session.clear и session.сброс

  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, запрос в режиме гибернации, критерии, у всех одинаковая проблема.

  4. В методе getPost postDAO: сначала я попытался загрузить данные с помощью собственного SQL и хотел сравнить с результатом запроса в режиме гибернации. оба запроса возвращают старые данные.

Код:

 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;

    }
  

Комментарии:

1. вы пробовали внедрять экземпляр сеанса в свой класс DAO, а не в factory?

Ответ №1:

У меня была такая же проблема. Ответ я нашел быстро. Как сказал Риккардо, проблема заключалась в не чистом закрытии сеанса, поэтому сеанс был случайным образом переработан. я сделал это в конструкторе класса.

Пример (я использовал здесь 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;
    }
}
  

спасибо за чтение

Ответ №2:

Похоже, что вы извлекаете список и отображаете только первую запись списка. Я предполагаю, что список заполняется более чем одним элементом, каждый раз в случайном порядке, поскольку нет критериев упорядочения по порядку.Таким образом, первый элемент списка может отличаться для разных исполнений.

Вы ожидаете уникального результата? Если это так, было бы лучше использовать Criteria.uniqueResult();

Ответ №3:

Это может зависеть от способа получения сеанса: если вы используете typycal HibernateUtil с ThreadLocal session, возможно, вы неправильно закрываете сеанс после завершения работы с ним. В этом случае сеанс почти случайным образом перерабатывается совершенно не связанными единицами работы, которые получат кэшированное значение