Java 休眠:C3p0池配置降低了整个服务器的速度。

Java 休眠:C3p0池配置降低了整个服务器的速度。,java,spring,postgresql,hibernate,c3p0,Java,Spring,Postgresql,Hibernate,C3p0,我正在开发一个SpringMVC应用程序,其中我们使用Hibernate和c3p0进行数据库事务和连接池。大多数情况下,它工作得非常好,没有问题。但在某些情况下,我必须在当前事务中复制大量对象和文件。当这种情况发生时,整个服务器的速度会减慢,最后我开始出现无法回滚异常。我的c3p0设置有问题吗?多谢各位 pom.xml: <!--- Hibernate dependencies --> <dependency> <group

我正在开发一个SpringMVC应用程序,其中我们使用Hibernate和c3p0进行数据库事务和连接池。大多数情况下,它工作得非常好,没有问题。但在某些情况下,我必须在当前事务中复制大量对象和文件。当这种情况发生时,整个服务器的速度会减慢,最后我开始出现
无法回滚异常。我的c3p0设置有问题吗?多谢各位

pom.xml:

 <!--- Hibernate dependencies -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
        </dependency>

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-c3p0</artifactId>
            <version>4.3.9.Final</version>
        </dependency>

org.hibernate
休眠验证器
org.hibernate
冬眠核心
org.hibernate
休眠实体管理器
org.hibernate
hibernate-c3p0
4.3.9.最终版本
root-context.xml:

<beans:bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
            destroy-method="close">
    <beans:property name="driverClassName" value="org.postgresql.Driver"/>
    <beans:property name="url"
                    value="jdbc:postgresql://localhost:PORT/DB_NAME"/>
    <beans:property name="username" value="USERNAME"/>
    <beans:property name="password" value="PASSWORD"/>
    <beans:property name="removeAbandoned" value="true"/>
    <beans:property name="removeAbandonedTimeout" value="20"/>
    <beans:property name="defaultAutoCommit" value="false"/>
</beans:bean>

<!-- Hibernate 4 SessionFactory Bean definition -->
<beans:bean id="hibernate4AnnotatedSessionFactory"
            class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <beans:property name="dataSource" ref="dataSource"/>
    <beans:property name="packagesToScan" value="com.ourapp.spring.model"/>
    <beans:property name="hibernateProperties">
        <beans:props>
            <beans:prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQL9Dialect</beans:prop>
            <beans:prop key="hibernate.show_sql">false</beans:prop>
               <!--<beans:prop key="hibernate.jdbc.batch_size">1000</beans:prop>-->
            <beans:prop key="hibernate.hbm2ddl.auto">update</beans:prop>
            <beans:prop key="cache.use_second_level_cache">true</beans:prop>
            <beans:prop key="cache.use_query_cache">true</beans:prop>
            <beans:prop key="hibernate.order_updates">true</beans:prop>
            <beans:prop key="show_sql">false</beans:prop>
            <beans:prop key="hibernate.c3p0.min_size">1</beans:prop>
            <beans:prop key="hibernate.c3p0.max_size">750</beans:prop>
            <beans:prop key="hibernate.c3p0.acquire_increment">1</beans:prop>
            <beans:prop key="hibernate.c3p0.idle_test_period">1000</beans:prop>
            <beans:prop key="hibernate.c3p0.max_statements">150</beans:prop>
            <beans:prop key="hibernate.c3p0.timeout">1200</beans:prop>
            <beans:prop key="hibernate.connection.release_mode">auto</beans:prop>
        </beans:props>
    </beans:property>

</beans:bean>

org.hibernate.dialogue.postgresql9dialogue
假的
更新
真的
真的
真的
假的
1.
750
1.
1000
150
1200
汽车

多谢各位

对于初学者来说,您不使用C3P0仅仅是因为您将
org.apache.commons.dbcp.BasicDataSource
配置为
数据源,并将其注入到
LocalSessionFactoryBean
中。这基本上会使所有的
hibernate.c3p0
设置无效,因为它们将被忽略

接下来,您会遇到处理大量数据的问题,我高度怀疑问题是您的
数据源或连接池,而是您处理实体的方式以及如何配置Hibernate

要加速批处理,您需要将每个x记录刷新到数据库中,并清除一级缓存。你可能会想知道,你为什么要这样做。这一切都与Hibernate的工作方式有关,当您持久化一个实体时,Hibernate所做的将把它添加到一级缓存中(JPA的
会话
实体管理器
)。每次将项目添加到一级缓存时,它都会对一级缓存中的所有实体进行脏检查,以确定是否需要刷新某些内容。现在,对于最初的几个实体,这将是快速的,但将变得越来越慢

让我们为批量大小为50的对象进行配置和编码

首先要将hibernate配置为具有适当的批处理大小,并对insert和update语句进行排序。如果您这样做,您将受益于JDBC现在可以执行批处理更新(即一条insert或Update语句来修改50条记录,而不是50条insert/Update语句)

休眠配置

org.hibernate.dialogue.postgresql9dialogue
假的
更新
真的
真的
50
真的
真的
真的
代码修改
public void yourLargeDataSetProcessingMethod(){
Session Session=sessionFactory.getCurrentSession();
int i=0;
对于(您的项目:列出项目){
i++:
//这里将是处理/创建
如果(i%50==0){
session.flush();
session.clear();
}
}
session.flush();
session.clear();
} 
这可能会加快处理和数据库锁定的速度

最后一个注意事项是,我建议使用Commons DBCP或C3P0作为连接池,而不是Commons DBCP或C3P0。它非常小,速度非常快,并且保持活跃(而C3P0已经休眠了相当一段时间)


是一个很好的资源(包括基准测试等),了解每个设置的作用、添加或删除性能以及如何正确配置

对于初学者来说,您不使用C3P0仅仅是因为您将
org.apache.commons.dbcp.BasicDataSource
配置为
数据源,并将其注入到
LocalSessionFactoryBean
中。这基本上会使所有的
hibernate.c3p0
设置无效,因为它们将被忽略

接下来,您会遇到处理大量数据的问题,我高度怀疑问题是您的
数据源或连接池,而是您处理实体的方式以及如何配置Hibernate

要加速批处理,您需要将每个x记录刷新到数据库中,并清除一级缓存。你可能会想知道,你为什么要这样做。这一切都与Hibernate的工作方式有关,当您持久化一个实体时,Hibernate所做的将把它添加到一级缓存中(JPA的
会话
实体管理器
)。每次将项目添加到一级缓存时,它都会对一级缓存中的所有实体进行脏检查,以确定是否需要刷新某些内容。现在,对于最初的几个实体,这将是快速的,但将变得越来越慢

让我们为批量大小为50的对象进行配置和编码

首先要将hibernate配置为具有适当的批处理大小,并对insert和update语句进行排序。如果您这样做,您将受益于JDBC现在可以执行批处理更新(即一条insert或Update语句来修改50条记录,而不是50条insert/Update语句)

休眠配置

org.hibernate.dialogue.postgresql9dialogue
假的
更新
真的
真的
50
真的
真的
真的
代码修改
public void yourLargeDataSetProcessingMethod(){
会话=ses
<beans:bean id="hibernate4AnnotatedSessionFactory"
            class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <beans:property name="dataSource" ref="dataSource"/>
    <beans:property name="packagesToScan" value="com.ourapp.spring.model"/>
    <beans:property name="hibernateProperties">
        <beans:props>
            <beans:prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQL9Dialect</beans:prop>
            <beans:prop key="hibernate.show_sql">false</beans:prop>
               <!--<beans:prop key="hibernate.jdbc.batch_size">1000</beans:prop>-->
            <beans:prop key="hibernate.hbm2ddl.auto">update</beans:prop>
            <beans:prop key="hibernate.cache.use_second_level_cache">true</beans:prop>
            <beans:prop key="hibernate.cache.use_query_cache">true</beans:prop>
            <beans:prop key="hibernate.jdbc.batch_size">50</beans:prop>
            <beans:prop key="hibernate.order_inserts">true</beans:prop>
            <beans:prop key="hibernate.order_updates">true</beans:prop>
            <!-- If you use versioned entities set this to true as well -->
            <beans:prop key="hibernate.jdbc.batch_versioned_data">true<beans:prop> 
        </beans:props>
    </beans:property>
</beans:bean>
public void yourLargeDataSetProcessingMethod() {
    Session session = sessionFactory.getCurrentSession();

    int i = 0;
    for (YourItem item : List<YourItem> items) {
        i++:
        // Here will be processing / creation

        if (i % 50 == 0) {
            session.flush();
            session.clear();
        }
    }
    session.flush();
    session.clear();
}