#mysql #hibernate #second-level-cache
#mysql #режим гибернации #кэш второго уровня
Вопрос:
Я столкнулся со странной проблемой с обновлением и отображением данных в режиме гибернации. Кто-нибудь может мне помочь, пожалуйста!?
Я использую hibernate, spring с mysql.
Проблема, с которой я сталкиваюсь, заключается в том, что любые изменения могут быть применены к базе данных. Но если я загружаю обновленный элемент на веб-страницу, он всегда возвращает старые данные или новые данные случайным образом.
Я уверен, что это не проблема кэша браузера. Я попытался распечатать возвращаемые данные в методе getPost в классе dao. Иногда он просто выводит неправильное сообщение.
Скажем, если я изменяю содержимое публикации несколько раз, все изменения могут быть сохранены в базе данных. Но если я постоянно обновляю страницу для отображения измененных данных, она отображает все предыдущие изменения случайным образом.
Я пробовал разные способы загрузки данных в метод getPost, но все еще сталкиваюсь с той же проблемой:
-
пробовал session.clear и session.сброс
-
закройте кэш второго уровня как :
<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>
-
разные способы загрузки данных: session.load, session.get, запрос в режиме гибернации, критерии, у всех одинаковая проблема.
-
В методе 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, возможно, вы неправильно закрываете сеанс после завершения работы с ним. В этом случае сеанс почти случайным образом перерабатывается совершенно не связанными единицами работы, которые получат кэшированное значение