我有一个奇怪的问题,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 :(得分:5)
我已经解决了。我有一个非汇集的数据源:
<bean name="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
简单实现标准JDBC DataSource接口,通过bean属性配置普通的旧JDBC DriverManager,并从每个getConnection调用返回一个新的Connection。 注意:此类不是实际的连接池;它实际上并没有池连接。它只是简单替代完整的连接池,实现相同的标准接口,但每次调用都会创建新的连接。
所以我现在将其替换为:
<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,因为它使用了那个连接池。