Hibernate Query Cache проблема - PullRequest
1 голос
/ 30 января 2012

Я обнаружил странную ошибку в моем приложении.Я упростил это, и вот как это можно воспроизвести:

(я использовал DbUnit для создания таблиц и HSQLDB в качестве базы данных, но на самом деле это не имеет значения)

package test;

import java.io.IOException;
import java.io.Serializable;
import java.io.StringReader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

import org.dbunit.DatabaseUnitException;
import org.dbunit.database.DatabaseConnection;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.xml.FlatXmlDataSetBuilder;
import org.dbunit.operation.DatabaseOperation;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.springframework.orm.hibernate3.HibernateTemplate;

public class DatabaseBugReproduction {

    @Entity(name = "A")
    @Table(name = "a")
    public static class A {

        private int     id;
        private Set <B> bs;

        @Id
        public int getId() {
            return id;
        }

        @ManyToMany
        @JoinTable(
            name = "ab",
            joinColumns = @JoinColumn(name = "a_id"),
            inverseJoinColumns = @JoinColumn(name = "b_id")
        )
        public Set <B> getBs() {
            return bs;
        }

        void setId(int id) {
            this.id = id;
        }

        void setBs(Set <B> engines) {
            this.bs = engines;
        }
    }

    @Entity(name = "B")
    @Table(name = "b")
    public static class B {

        private int id;

        @Id
        public int getId() {
            return id;
        }

        void setId(int id) {
            this.id = id;
        }
    }

    private static SessionFactory getSessionFactory() throws SQLException, IOException, DatabaseUnitException {
        String driverClass = "org.hsqldb.jdbc.JDBCDriver";
        String jdbcUrl = "jdbc:hsqldb:mem:seoservertooltest";
        String dbUsername = "test";
        String dbPassword = "test";
        String dbDialect = "org.hibernate.dialect.HSQLDialect";
        Configuration config = new Configuration()//
        .setProperty("hibernate.connection.driver_class", driverClass)//
        .setProperty("hibernate.connection.url", jdbcUrl)//
        .setProperty("hibernate.connection.username", dbUsername)//
        .setProperty("hibernate.connection.password", dbPassword)//
        .setProperty("hibernate.dialect", dbDialect)//
        .setProperty("hibernate.hbm2ddl.auto", "create-drop")//
        .setProperty("hibernate.current_session_context_class", "thread")//
        .setProperty("hibernate.cache.use_query_cache", "true")//
        .setProperty("hibernate.cache.use_second_level_cache", "true")//
        .setProperty("hibernate.cache.region.factory_class", "net.sf.ehcache.hibernate.EhCacheRegionFactory")//
        .setProperty("hibernate.cache.region_prefix", "")//
        // .setProperty("hibernate.show_sql", "true")//
        // .setProperty("hibernate.format_sql", "true")//
        .addAnnotatedClass(A.class) //
        .addAnnotatedClass(B.class) //
        ;
        SessionFactory result = config.buildSessionFactory();
        try (Connection con = DriverManager.getConnection(jdbcUrl, dbUsername, dbPassword)) {
            con.createStatement().executeUpdate("SET DATABASE REFERENTIAL INTEGRITY FALSE;");
            String xml = "<?xml version='1.0' encoding='UTF-8'?>"//
                    + "<dataset>"//
                    + "<a id='1'/>"//
                    + "<b id='1'/>"//
                    + "<ab a_id='1' b_id='1' />"//
                    + "</dataset>";
            final IDatabaseConnection dbCon = new DatabaseConnection(con);
            try {
                final FlatXmlDataSetBuilder builder = new FlatXmlDataSetBuilder();
                final IDataSet dataSet = builder.build(new StringReader(xml));
                DatabaseOperation.CLEAN_INSERT.execute(dbCon, dataSet);
            } finally {
                dbCon.close();
            }
        }
        return result;
    }

    public static void main(String[] args) throws Exception {
        HibernateTemplate hibTemplate = new HibernateTemplate(getSessionFactory());
        hibTemplate.setCacheQueries(true);
        System.out.println(hibTemplate.find("select a.bs from A a"));
        System.out.println(hibTemplate.find("select a.bs from A a"));
    }
}

Вывод:

[test.DatabaseBugReproduction$B@2942ce]
[null]

Похоже, что кеш каким-то образом неправильно настроен.Где ошибка и как ее исправить?

Используется:

  • JDK 1.7.0_01 как x32, так и x64
  • Hibernate 3.6.7
  • Ehcache 2.5.0
  • Spring 3.1.0
  • База данных: работает как минимум с HSQLDB, H2 и MySQL

1 Ответ

2 голосов
/ 11 февраля 2012

После некоторой отладки я обнаружил, что, похоже, проблема с кешем запросов и запросами к сбору. Метод, который рассеивает коллекции для хранения в кеше, всегда возвращает null.

Фактически, после поиска в Google, оказывается, что эта проблема связана с ошибкой в Hibernate. См. Описание проблемы для получения дополнительной информации.

Хотя эта проблема не устранена (кажется, что это не так), вы можете переписать запрос, чтобы вам не требовался запрос на коллекцию:

public static void main(String[] args) throws Exception {
    HibernateTemplate hibTemplate = new HibernateTemplate(getSessionFactory());
    hibTemplate.setCacheQueries(true);
    //System.out.println(hibTemplate.find("select a.bs from A a"));
    //System.out.println(hibTemplate.find("select a.bs from A a"));
    System.out.println(hibTemplate.find("select bs from A a inner join a.bs as bs"));
    System.out.println(hibTemplate.find("select bs from A a inner join a.bs as bs"));
}

Я проверил это, и он отлично работает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...