我正在使用 spring / hibernate / mysql ,目前在 spring-hibernate.xml中 使用以下设置
我经常看到 “ select @@ session.tx_read_only” 和 “ select @@ session.tx_isolation” 查询主要在选择实际数据的语句之后发送到数据库。
这些查询中的每一个都会增加20-25毫秒的时间,而在Oauth登录上,我会针对数据库运行70个查询。我该如何摆脱它们?
我尝试了statelessSessions,查询消失了,只能将查询数量减少到应用程序查询,但是我读到,使用statelessSessions不会提供任何一级缓存,并且也容易受到数据混叠的影响。
如何避免多次运行“ select @@ session.tx_read_only”和select @@ session.tx_isolation。(我使用通用Dao访问数据库,下面提供了摘录)我正在使用findById,findAll,getNamedQueryAndNamedParam方法…
spring-hibernate.xml
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <property name="driverClass" value="com.mysql.jdbc.Driver" /> <property name="jdbcUrl" value="${JDBC_CON_STRING}" /> <property name="user" value="${USER_NAME}" /> <property name="password" value="${USER_PASSWORD}" /> </bean> <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="packagesToScan" value="com.model" /> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.format_sql">true</prop> <prop key="hibernate.hbm2ddl.auto">false</prop> <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop> <prop key="hibernate.cache.use_query_cache">true</prop> <prop key="hibernate.cache.use_second_level_cache">true</prop> <prop key="hibernate.cache.provider_configuration_file_resource_path">ehcach.xml</prop> <prop key="hibernate.auto_close_session">true</prop> </property> <property name="mappingResources"> <list> <value>named-queries.xml</value> <value>native-named-queries.xml</value> </list> </property> </bean> <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> <property name="dataSource" ref="dataSource" /> </bean> <tx:annotation-driven transaction-manager="transactionManager" /> <bean id="testClassDao" class="com.dao.GenericHibernateDao"> <property name="clazz" value="com.model.TestClass" /> </bean>
GenericHibernateDao.java
@Repository @Scope("prototype") public class GenericHibernateDao<T, PK extends Serializable> implements GenericDao<T, PK> { private Class<T> clazz; @Autowired private SessionFactory sessionFactory; public void setClazz(final Class<T> clazzToSet) { this.clazz = clazzToSet; } protected Session getSession() { return sessionFactory.getCurrentSession(); } protected Session getOpenSession() { return sessionFactory.openSession(); } @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED) public T findById(PK id) { Object obj = null; obj = getSession().get(clazz, id); //obj = getStatelessSession().get(clazz, id); return (T) obj; } @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED) public List<T> findAll() { String queryString = "from " + clazz.getName(); Query query = getSession().createQuery(queryString); query.setCacheable(true); List<T> list = query.list(); return list; } @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED) public List<T> getNamedQuery(String queryName) { Query query = getSession().getNamedQuery(queryName); //Query query = getStatelessSession().getNamedQuery(queryName); query.setCacheable(true); List<T> results = query.list(); return results; } @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED) public List<T> getNamedQueryAndNamedParam(String queryName, String paramName, Object value) { Query query = getSession().getNamedQuery(queryName).setString(paramName, value.toString()); query.setCacheable(true); List<T> results = query.list(); return results; } @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED) public PK save(T persistenceObject) { Serializable save = getSession().save(persistenceObject); return (PK) save; } @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED) public void saveOrUpdate(T persistenceObject) { getSession().saveOrUpdate(persistenceObject); } public void saveOrUpdateBulk(Collection<T> persistenceObject) { Session session = getOpenSession(); Transaction tx = session.beginTransaction(); int i = 0; for (Iterator<T> iterator = persistenceObject.iterator(); iterator.hasNext();) { i++; session.saveOrUpdate(iterator.next()); if (i % 100 == 0) { session.flush(); session.clear(); } } tx.commit(); session.close(); } @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED) public boolean delete(PK id) { Object findById = findById(id); if (findById != null) { getSession().delete(findById); return true; } return false; } }
AFAIK要删除这些多余的查询,请删除@Transactional注释的所有修饰符。将隔离级别限制为的代价READ_COMMITED是Hibernate需要执行额外的查询以确定数据库是否处于脏状态。对于90%的情况,这些修饰符是不必要的。Hibernate非常擅长确保您的数据干净,而无需尝试添加这些限制。
@Transactional
READ_COMMITED
如果绝对需要确保隔离度为READ_COMMITTED,则您不能对多余的查询做任何事情。
READ_COMMITTED
StatelessSession出于您指出的原因,转移到公正来摆脱这些查询是一个坏主意。确实,使用a的唯一有效理由StatelessSession是对大批量的插入数据进行了插入,而您知道这些数据不会在插入过程中被读取。
StatelessSession