2010-04-06 67 views
2

我有一個奇怪的問題,其中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()的調用需要大約140ms的......莫名其妙。數據庫對其他查詢執行得很好,其中包括一些處理程序(我懷疑它不是第一個查詢運行時)。

的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' 

它明確指出,實際的查詢需要沒有時間,而且大部分時間是在第四個花費。我能做些什麼呢?它不會在hibernate日誌輸出中顯示,只有第一個實際查詢會顯示。順便說一句,之後的所有時間都是之後調用getJpaTemplate() - 即實際上在jpa.find()方法中。

任何想法?

更新:我已經發現它是hibernate做多次與數據庫的初始連接,因爲有人發佈了相同的一組查詢(http://ondra.zizka.cz/stranky/programovani/java/hibernate_netbeans_howto_tutorial.texy)。爲什麼hibernate會重複進行初始連接,是不是使用連接池 - 我該如何檢查?

+0

您應該編輯您的問題並正確設置代碼格式。在編輯器中突出顯示它,然後單擊工具欄上的「101010」按鈕。 – 2010-04-06 21:25:07

+0

我知道,我已經付出了巨大的努力,但是由於我使用了製表符,這個網站將它們變成了空格,當我保存時它就丟失了 - 即使它在預覽中看起來很好。我應該提交一份錯誤報告,以防他們不知道! – gubby 2010-04-06 21:26:47

回答

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接口,通過bean的屬性配置普通的舊JDBC的DriverManager,並返回一個新的來自每個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拋出過,因爲它使用連接池:

所以我現在換成這個。