Hibernate向数据库发送了多余的查询

3
我有一个奇怪的问题,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) [5毫秒] 选择用户...(实际查询)
2) [7毫秒] 显示排序规则
3) [14毫秒] /* mysql-connector-java-5.1.7 (修订版:${svn.Revision}) */SELECT @@session.auto_increment_increment
4) [70毫秒] /* mysql-connector-java-5.1.7 (修订版:${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会重复进行初始连接,它不是使用连接池吗?我该如何检查?


你应该编辑你的问题并正确格式化代码。在编辑器中将其突出显示,然后单击工具栏上的“101010”按钮。 - Mike Daniels
我知道,我已经付出了很大的努力,但由于我使用制表符,这个网站把它们转换成了空格,并且在保存时丢失了 - 即使在预览中看起来很好。我应该提交一个错误报告,以防他们不知道! - gub
1个回答

5

我解决了问题。原来我使用的是非连接池数据源:

<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 调用时返回一个新的 Connection。 注意:这个类不是一个真正的连接池;它实际上不会池化 Connections。它只是作为一个完整的连接池的简单替代,实现相同的标准接口,但在每次调用时创建新的 Connections。

所以我现在用以下内容替换了它:

<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,因为它使用了这个连接池。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接