gpt4 book ai didi

java - Hibernate 中不必要的查询 - MySql

转载 作者:行者123 更新时间:2023-11-29 00:12:46 25 4
gpt4 key购买 nike

我正在使用 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;
}
}

最佳答案

据我所知,要删除那些额外的查询,请删除对 @Transactional 注释的所有修饰符。将隔离级别限制为 READ_COMMITED 的代价是 Hibernate 将需要执行额外的查询以确定数据库是否处于脏状态。对于 90% 的情况,这些修饰符是不必要的。 Hibernate 非常擅长确保您的数据干净,而无需您尝试添加这些限制。

如果您绝对有必要确保您的隔离是 READ_COMMITTED,则您不能对额外的查询做任何事情。

移动到 StatelessSession 只是为了摆脱这些查询是一个坏主意,这正是您指出的原因。实际上,使用 StatelessSession 的唯一正当理由是用于大批量插入您知道在插入发生时不会读取的数据。

关于java - Hibernate 中不必要的查询 - MySql,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24276196/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com