简体   繁体   English

Hibernate中不必要的查询-MySQL

[英]Unnecessary queries in Hibernate - MySql

I am using spring / hibernate / mysql and currently using the following settings in spring-hibernate.xml 我正在使用spring / hibernate / mysql ,目前在spring-hibernate.xml中使用以下设置

I am constantly seeing "select @@session.tx_read_only" and "select @@session.tx_isolation" queries being sent to the DB mostly after select statements for actual data. 我经常看到“ select @@ session.tx_read_only”“ select @@ session.tx_isolation”查询主要在选择实际数据的语句之后发送到数据库。

Each of these queries add like 20-25ms time and I get like 70 queries run against the DB on a Oauth login. 这些查询中的每一个都会增加20-25毫秒的时间,而在Oauth登录上,我会针对数据库运行70个查询。 How can I get rid of them ? 我该如何摆脱它们?

I tried statelessSessions and the queries disappeared and I could reduce the number of queries to the application queries only but I read that using statelessSessions will not provide any first-level cache and its also vulnerable to data aliasing effects. 我尝试了statelessSessions,查询消失了,只能将查询数量减少到应用程序查询,但是我读到,使用statelessSessions不会提供任何一级缓存,并且也容易受到数据混叠的影响。

How can I avoid the "select @@session.tx_read_only" and select @@session.tx_isolation" running multiple times.(I use a generic Dao to access the DB a extract is given below) i am using findById, findAll, getNamedQueryAndNamedParam methods... 如何避免多次运行“ select @@ session.tx_read_only”和select @@ session.tx_isolation。(我使用通用Dao访问数据库,下面提供了摘录)我正在使用findById,findAll,getNamedQueryAndNamedParam方法...

spring-hibernate.xml 弹簧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 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 to remove those extra queries, remove all your modifiers to your @Transactional annotations. AFAIK要删除这些多余的查询,请删除@Transactional批注的所有修饰符。 The price you pay for restricting your isolation level to READ_COMMITED is that Hibernate will need to perform extra queries to determine if the database is in a dirty state. 将隔离级别限制为READ_COMMITED的代价是Hibernate将需要执行额外的查询以确定数据库是否处于脏状态。 For 90% of cases, these modifiers are unnecessary. 对于90%的情况,这些修饰符是不必要的。 Hibernate is very good at ensuring that your data will be clean without you trying to add these restrictions. Hibernate非常擅长确保您的数据干净,而无需尝试添加这些限制。

If it is absolutely necessary for you to ensure that your isolation is READ_COMMITTED , you can't do anything about the extra queries. 如果绝对有必要确保隔离是READ_COMMITTED ,那么您就无法对多余的查询做任何事情。

Moving to a StatelessSession just to get rid of those queries is a bad idea for exactly the reason you pointed out. 正是出于您指出的原因,转移到StatelessSession来摆脱这些查询是一个坏主意。 Really, the only valid reason to be using a StatelessSession is for large batch inserts of data that you know won't be read while the insert is occuring. 确实,使用StatelessSession的唯一有效理由是对插入的大批数据进行了插入,而您知道这些数据不会在插入过程中被读取。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM