我有一个奇怪的问题,Hibernate 运行的查询比我要求的要多,而且看不到需要。
这是我的控制器:
@Autowired UserService users;
@RequestMapping("/test")
@ResponseBody
public String test() {
User user = users.findUser(1L);
return "Found user: "+user.getEmail();
}
这是用户服务:
@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]选择用户...(实际查询) 2) [7ms] 显示排序 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' 或 Variable_name = 'character_set_client' 或 Variable_name = 'character_set_connection' 或 Variable_name = 'character_set' 或 Variable_name = 'character_set_server' 或 Variable_name = 'tx_isolation' 或 Variable_name = 'transaction_isolation' 或 Variable_name = 'character_set_results' 或 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)。为什么休眠会反复进行初始连接,不是使用连接池吗?我该如何检查?