Hibernate отправка лишних запросов в базу данных - PullRequest
3 голосов
/ 07 апреля 2010

У меня странная проблема, когда Hibernate выполняет больше запросов, чем я просил, и не вижу необходимости в этом.

Вот мой контроллер:

@Autowired UserService users;

@RequestMapping("/test")
@ResponseBody
public String test() {
    User user = users.findUser(1L);
    return "Found user: "+user.getEmail();
}

Вот UserService :

@Component
public class UserService {

    @javax.persistence.PersistenceUnit private EntityManagerFactory emf;

    private JpaTemplate getJpaTemplate() {
        return new JpaTemplate(emf);
    }

    public User findUser(long id) {
        long start = System.currentTimeMillis();
        JpaTemplate jpaTemplate = getJpaTemplate();
        User user = jpaTemplate.find(User.class, id);
        System.out.println(System.currentTimeMillis() - start);
        return user;
    }
}

Вызов findUser () занимает около 140 мс ... Скорее сбивает с толку. База данных отлично работает для других запросов, включая этот в некоторых обработчиках (подозреваю, что это не первый запуск запроса).

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

1) [5ms] select user... (the actual query)

2) [7ms] SHOW COLLATION

3) [14ms] /* mysql-connector-java-5.1.7 ( Revision: ${svn.Revision} ) */SELECT @@session.auto_increment_increment

4) [70ms] /* mysql-connector-java-5.1.7 ( Revision: ${svn.Revision} ) */SHOW VARIABLES WHERE Variable_name ='language' OR Variable_name = 'net_write_timeout' OR Variable_name = 'interactive_timeout' OR Variable_name = 'wait_timeout' OR Variable_name = 'character_set_client' OR Variable_name = 'character_set_connection' OR Variable_name = 'character_set' OR Variable_name = 'character_set_server' OR Variable_name = 'tx_isolation' OR Variable_name = 'transaction_isolation' OR Variable_name = 'character_set_results' OR Variable_name = 'timezone' OR Variable_name = 'time_zone' OR Variable_name = 'system_time_zone' OR Variable_name = 'lower_case_table_names' OR Variable_name = 'max_allowed_packet' OR Variable_name = 'net_buffer_length' OR Variable_name = 'sql_mode' OR Variable_name = 'query_cache_type' OR Variable_name = 'query_cache_size' OR Variable_name = 'init_connect'

Понятно, что фактический запрос вообще не требует времени, и большую часть времени тратит на этот четвертый. Что я могу сделать по этому поводу? Он не отображается в выводе журнала гибернации, а только первый фактический запрос. Кстати, все время тратится после вызова getJpaTemplate () - т.е. фактически в методе jpa.find ().

Есть идеи?

ОБНОВЛЕНИЕ: я выяснил, что это спящий режим, когда несколько раз выполнялось какое-то первоначальное соединение с базой данных, поскольку кто-то другой отправил такой же набор запросов (http://ondra.zizka.cz/stranky/programovani/java/hibernate_netbeans_howto_tutorial.texy). Почему бы hibernate повторно устанавливал свое первоначальное соединение Разве это не с помощью пула соединений - как я могу проверить?

1 Ответ

5 голосов
/ 07 апреля 2010

Я решил это.У меня был источник данных без пула:

<bean name="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">

Из Javadoc по адресу: http://static.springsource.org/spring/docs/2.0.x/api/org/springframework/jdbc/datasource/DriverManagerDataSource.html

Простая реализация стандартного интерфейса JDBC DataSource, настройка простого старого JDBC DriverManager черезсвойства bean-компонента и возвращение нового Connection из каждого вызова getConnection.ПРИМЕЧАНИЕ. Этот класс не является фактическим пулом соединений;на самом деле он не объединяет соединения.Он просто служит простой заменой полноценного пула соединений, реализуя тот же стандартный интерфейс, но создавая новые Соединения при каждом вызове.

Итак, я заменил это на:

<bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="com.mysql.jdbc.Driver"/> 
    <property name="jdbcUrl" value="jdbc:mysql://server.domain/database"/> 
    <property name="user" value="theUsername"/> 
    <property name="password" value="thePassword"/> 
</bean>

Мне также пришлось добавить c3p0-0.9.1.2.jar, поскольку он использует этот пул соединений.

...