Performance 改为OpentransactionPerView@Transactional
我有一个带有Spring3.1.1和Hibernate4.1的JavaEE应用程序。现在我想加快速度,发现瓶颈是在一个请求中打开和关闭多个事务 现在,我删除了所有的Performance 改为OpentransactionPerView@Transactional,performance,spring,hibernate,transactional,open-session-in-view,Performance,Spring,Hibernate,Transactional,Open Session In View,我有一个带有Spring3.1.1和Hibernate4.1的JavaEE应用程序。现在我想加快速度,发现瓶颈是在一个请求中打开和关闭多个事务 现在,我删除了所有的@Transactional注释,并创建了自己的OpenSessionInViewFilter,它可以打开和关闭一个事务 package utils.spring; import java.io.IOException; import javax.servlet.FilterChain; import javax.servlet.
@Transactional
注释,并创建了自己的OpenSessionInViewFilter
,它可以打开和关闭一个事务
package utils.spring;
import java.io.IOException;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate4.SessionFactoryUtils;
import org.springframework.orm.hibernate4.SessionHolder;
import org.springframework.orm.hibernate4.support.OpenSessionInViewFilter;
import org.springframework.transaction.support.TransactionSynchronizationManager;
public class CustomHibernateSessionViewFilter extends OpenSessionInViewFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
SessionFactory sessionFactory = lookupSessionFactory(request);
boolean participate = false;
if (TransactionSynchronizationManager.hasResource(sessionFactory)) {
// Do not modify the Session: just set the participate flag.
participate = true;
} else {
logger.debug("Opening Hibernate Session in OpenSessionInViewFilter");
Session session = openSession(sessionFactory);
TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
//BEGIN TRANSACTION
session.beginTransaction();
}
try {
filterChain.doFilter(request, response);
}
finally {
if (!participate) {
SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager.unbindResource(sessionFactory);
// COMMIT
sessionHolder.getSession().getTransaction().commit();
logger.debug("Closing Hibernate Session in OpenSessionInViewFilter");
SessionFactoryUtils.closeSession(sessionHolder.getSession());
}
}
}
}
这是个好主意吗?它似乎起了作用,加快了速度
以下是我的交易日志:
http-bio-8080-exec-3 01/03/2013 11:25:20,947 | DEBUG | org.springframework.orm.hibernate4.HibernateTransactionManager | doGetTransaction | Found thread-bound Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=[] updates=[] deletions=[] collectionCreations=[] collectionRemovals=[] collectionUpdates=[] unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])] for Hibernate transaction
http-bio-8080-exec-3 01/03/2013 11:25:20,948 | DEBUG | org.springframework.orm.hibernate4.HibernateTransactionManager | getTransaction | Creating new transaction with name [by2.server.service.UserService.loadUserByUsername]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
http-bio-8080-exec-3 01/03/2013 11:25:20,948 | DEBUG | org.springframework.orm.hibernate4.HibernateTransactionManager | doBegin | Preparing JDBC Connection of Hibernate Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=[] updates=[] deletions=[] collectionCreations=[] collectionRemovals=[] collectionUpdates=[] unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])]
http-bio-8080-exec-3 01/03/2013 11:25:21,172 | DEBUG | org.springframework.orm.hibernate4.HibernateTransactionManager | doBegin | Exposing Hibernate transaction as JDBC transaction [org.hibernate.engine.jdbc.internal.proxy.ConnectionProxyHandler@1e7b64f4[valid=true]]
http-bio-8080-exec-3 01/03/2013 11:25:21,188 | DEBUG | org.hibernate.SQL | logStatement | select userentity_.userID as userID5_ from users userentity_ where userentity_.username=?
连接池
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-c3p0</artifactId>
<version>4.1.1.Final</version>
</dependency>
<property name="hibernateProperties">
<value>
hibernate.hbm2ddl.auto=update
hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
hibernate.bytecode.use_reflection_optimizer=false
hibernate.max_fetch_depth=0
hibernate.c3p0.min_size=5
hibernate.c3p0.max_size=20
hibernate.c3p0.timeout=300
hibernate.c3p0.max_statements=50
hibernate.c3p0.idle_test_period=3000
</value>
</property>
但即使我移除了过滤器,Hibernate似乎也不使用池。我会说不
例如,您将在数据库中保存一些产品或其他内容,并显示一个成功页面或重定向,认为所有内容都已保存。但该事务尚未提交,并且在显示成功消息后仍可能回滚
在Hibernate中,发生这种情况的可能性更大,因为在刷新时间之前不会向数据库写入任何内容,而刷新时间正好在提交之前发生
此外,事务的生命周期将超过必要的时间,如果它锁定了数据库中的行或表,则会阻止处理其他事务,从而导致性能和可伸缩性较差
默认的SpringOpenSessionInviewFilter有什么问题,它允许会话打开,但仍然使用服务级别的短事务?为什么您的请求会打开多个事务?我的问题是,您在一个请求中执行了太多从UI层到服务层的调用。最后,我以正确的方式配置了我的池。。。解决方案不是向我的hibernate配置中添加一些c3p0属性,我只是需要替换我的数据源bean
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<!-- Connection properties -->
<property name="driverClass" value="org.postgresql.Driver" />
<property name="jdbcUrl" value="jdbc:postgresql://localhost:5432/DBNAME" />
<property name="user" value="xxx" />
<property name="password" value="xxx" />
<!-- Pool properties -->
<property name="minPoolSize" value="5" />
<property name="maxPoolSize" value="20" />
<property name="maxStatements" value="50" />
<property name="idleConnectionTestPeriod" value="3000" />
<property name="loginTimeout" value="300" />
</bean>
现在运行起来很有魅力没错,每个打开的事务大约需要200毫秒=(>>我的问题是,您在一个请求中从UI层到服务层的调用太多。如果您只需要200毫秒来打开一个事务,则在某些地方配置错误。连接池配置是否正确?这200毫秒花在哪里?您测量了吗?是的,添加了一个日志片段,我需要每个请求3个事务:s获取用户、我自己的安全iminterceptor和实际执行工作的rest处理程序的Spring security=(给定日志,获取JDBC连接需要时间。您是否使用连接池?如果是,那么是哪一个,以及如何配置?
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<!-- Connection properties -->
<property name="driverClass" value="org.postgresql.Driver" />
<property name="jdbcUrl" value="jdbc:postgresql://localhost:5432/DBNAME" />
<property name="user" value="xxx" />
<property name="password" value="xxx" />
<!-- Pool properties -->
<property name="minPoolSize" value="5" />
<property name="maxPoolSize" value="20" />
<property name="maxStatements" value="50" />
<property name="idleConnectionTestPeriod" value="3000" />
<property name="loginTimeout" value="300" />
</bean>