【问题标题】:Hibernate sending superfluous queries to the databaseHibernate 向数据库发送多余的查询
【发布时间】:2011-02-05 00:23:46
【问题描述】:

我有一个奇怪的问题,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_pa​​cket' OR Variable_name = 'net_buffer_length' OR Variable_name = 'sql_mode' OR Variable_name = 'query_cache_type' OR Variable_name = 'query_cache_size'或 Variable_name = 'init_connect'

很明显,实际查询根本不需要时间,大部分时间都花在第四个查询上。我能做些什么呢?它不会出现在休眠日志输出中,只有第一个实际查询会出现。顺便说一句,所有时间都花在调用 getJpaTemplate() 之后 - 即实际上是在 jpa.find() 方法中。

有什么想法吗?

更新:我发现它是休眠多次与数据库进行某种初始连接,因为其他人发布了相同的查询集 (http://ondra.zizka.cz/stranky/programovani/java/hibernate_netbeans_howto_tutorial.texy)。为什么hibernate会反复进行初始连接,不是使用连接池吗?我该如何检查?

【问题讨论】:

  • 您应该编辑您的问题并正确格式化代码。在编辑器中突出显示它,然后单击工具栏上的“101010”按钮。
  • 我知道,我为此付出了巨大的努力,但由于我使用了标签,这个网站把它们变成了空格,当我保存时它就丢失了——尽管它在预览中看起来很好。我应该提交一份错误报告,以防他们不知道!

标签: java mysql hibernate spring jprofiler


【解决方案1】:

我已经解决了。我有一个非池化数据源:

<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。 注意:这个类不是一个实际的连接池;它实际上并不池连接。它只是作为成熟连接池的简单替代品,实现相同的标准接口,但在每次调用时都会创建新的连接。

所以我现在将其替换为:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-01-04
    • 1970-01-01
    • 2023-03-18
    • 1970-01-01
    • 2018-10-03
    • 2013-08-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多