[英]Unnecessary queries in Hibernate - MySql
我正在使用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方法...
彈簧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非常擅長確保您的數據干凈,而無需嘗試添加這些限制。
如果絕對有必要確保隔離是READ_COMMITTED
,那么您就無法對多余的查詢做任何事情。
正是出於您指出的原因,轉移到StatelessSession
來擺脫這些查詢是一個壞主意。 確實,使用StatelessSession
的唯一有效理由是對插入的大批數據進行了插入,而您知道這些數據不會在插入過程中被讀取。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.