2010-04-06 56 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抛出过,因为它使用连接池:

所以我现在换成这个。