2010-04-06 1 views
2

У меня есть странная проблема, когда Hibernate запускает больше запросов, чем я просил, и не вижу необходимости.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 делает свое первоначальное соединение повторно, не использует ли пул соединений - как я могу проверить?

+0

Вы должны отредактировать свой вопрос и правильно отформатировать код. Выделите его в редакторе и нажмите кнопку «101010» на панели инструментов. –

+0

Я знаю, что я очень старался это сделать, но поскольку я использую вкладки, этот сайт превращал их в пробелы, и он был потерян, когда я спасал - хотя это выглядело отлично в предварительном просмотре. Я должен подать отчет об ошибке, если они не знают! – gubby

ответ

4

Я решил. Я был без объединенного источника данных:

<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 через свойство фасоли, и возвращая новый Соединение с каждым вызовом getConnection. ПРИМЕЧАНИЕ. Этот класс не является реальным пулом соединений; он фактически не объединяет Connections. Он просто служит простой заменой полномасштабного пула соединений, реализующего один и тот же стандартный интерфейс, но создавая новые соединения для каждого вызова.

Так что я теперь заменены это с:

<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 тоже, так как он использует, что пул соединений.