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)。为什么休眠会重复进行初始连接,它不是使用连接池吗 - 我该如何检查?
I have an odd problem where Hibernate is running more queries than I've asked for, and can't see the need for.
Here is my controller:
@Autowired UserService users;
@RequestMapping("/test")
@ResponseBody
public String test() {
User user = users.findUser(1L);
return "Found user: "+user.getEmail();
}
Here is the 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;
}
}
The call to findUser() takes about 140ms... Rather baffling. The database performs just fine for other queries, including this one in some handlers (I suspect when it is not the first query run).
JProfiler suggests that every time it is called, four queries are sent to the database (not necessarily in this order):
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'
Its clear that the actual query takes no time at all, and most of the time is spend in that fourth one. What can I do about this? It doesn't show up in the hibernate log output, only the first, actual query does. Incidentally, all the time is spent after the call to getJpaTemplate() - i.e actually in the jpa.find() method.
Any ideas?
UPDATE: I've worked out that it is hibernate doing some sort of initial connection to the database multiple times, since somebody else posted the same set of queries (http://ondra.zizka.cz/stranky/programovani/java/hibernate_netbeans_howto_tutorial.texy). Why would hibernate make its initial connection repeatedly, isn't it using a connection pool - how can I check?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我已经解决了。我有一个非池化数据源:
来自Javadoc: http://static.springsource.org/spring/docs/2.0.x/api/org/springframework/jdbc/datasource/DriverManagerDataSource.html
所以我现在将其替换为:
我也必须放入 c3p0-0.9.1.2.jar,因为它使用该连接池。
I've solved it. I had a non-pooled datasource:
From the Javadoc at: http://static.springsource.org/spring/docs/2.0.x/api/org/springframework/jdbc/datasource/DriverManagerDataSource.html
So I've now replaced this with:
I had to throw in c3p0-0.9.1.2.jar too, since it uses that connection pool.