【问题标题】:Hibernate - Keeping Entities in sync with batch database updatesHibernate - 使实体与批量数据库更新保持同步
【发布时间】:2011-07-12 14:14:43
【问题描述】:

您好,我希望就以下问题获得一些意见。我是 Hibernate 的新手,我正在努力解决这个问题。

问题:我的数据库中有每天更新一次的数据。我想让我的实体与此同步并刷新它们。我实现了一个 Spring/Quartz 计时器来调用我的休眠实现类来刷新实体。我试图确保每次调用此方法时都会清除所有当前实体,以便刷新它们。最好的方法是什么?

使用与 Spring 集成的 Hibernate 3.2。

建议的解决方案:

  1. 这是我使用实体管理器来管理它们的地方吗?

我尝试在 Session.flush 命令和 SesionFactory clear 上使用,但它不起作用。

Spring/Hibernate 配置

    <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
                    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                    http://www.springframework.org/schema/context
                    http://www.springframework.org/schema/context/spring-context-3.0.xsd
                    http://www.springframework.org/schema/util
                    http://www.springframework.org/schema/util/spring-util-3.0.xsd">


    <!--     Defines the hibernate session factory to be used by the hibernate support dao classes -->
    <bean id="hibernateSessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" >
        <property name="dataSource" ref="webDataSrc" />
        <property name="annotatedClasses"> 
                <list> 
                        <value>test.foo</value> 
                </list> 
        </property>

        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="debug">true</prop>
                <prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop>
                <prop key="hibernate.cglib.use_reflection_optimizer">false</prop>
            </props>
        </property>
    </bean>

    <!-- get the datasource from the context -->
    <bean id="webDataSrc" class="org.springframework.jndi.JndiObjectFactoryBean" lazy-init="true">
        <property name="jndiName" value="java:comp/env/datasource"/>
    </bean>

    <bean id="daoTxTemplate" abstract="true"
        class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <property name="transactionManager" ref="transactionManager" />
        <property name="transactionAttributes">
            <props>
                <prop key="get*">
                    PROPAGATION_REQUIRED,ISOLATION_READ_COMMITTED
                </prop>
            </props>
        </property>
    </bean>

    <bean name="openSessionInViewInterceptor"
        class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
        <property name="sessionFactory" ref="hibernateSessionFactory" />
        <property name="singleSession" value="true" />
    </bean>
    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="hibernateSessionFactory"/>
        <property name="nestedTransactionAllowed" value="true" />

    </bean>

【问题讨论】:

    标签: hibernate


    【解决方案1】:

    你可以在这里做几件事。如果您使用查询缓存,我建议使用Query.setCacheMode(CacheMode.REFRESH)。这将在查询期间强制刷新实体。

    Hibernate Documentation 确实声明...

    这在基础数据可能包含 已通过单独的进程更新

    您也可以使用SessionFactory.evictQueries(),但这会删除所有查询缓存,这可能有点过头了。

    最后,您还可以使用EntityManager.refresh(entity) 重新加载已知的特定实体。

    【讨论】:

    • @Micheal - 我将 Query.setCacheMode(CacheMode.REFRESH) 。但是我注意到我得到了一个 #org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here# 。要设置与 java 线程相关的新事务,我必须明确使用 beginTransaction 正确吗?还是我可以通过上面定义的 SessionFactory 做到这一点?
    • 看起来您正在使用事务管理器,因此您应该能够在执行事务的方法调用上使用 @Transactional 注释。查看 Spring 事务的文档。这将打开和关闭交易,因此您不必管理它们。
    • 是的,我实现了@Transactional 注释。非常漂亮和干净。很高兴不必使用 beginTransaction,关闭,终于写完了代码。
    【解决方案2】:

    为什么您的 Hibernate 会话保持打开这么长时间?它们不应该打开一天或更长时间。你应该打开会话,读取数据,做你的事情,然后关闭会话。如果您需要在会话之间保留数据,则应使用自己的缓存。

    当这些每日更新完成时,您会在数据库中保留一些审计跟踪,对吗?因此,每次打开 Hibernate 会话时,请检查您的内部缓存是否是最新的。如果在填充缓存后数据库中的数据已更新,则转储缓存并重新加载。

    【讨论】:

    • 我不同意。我认为他没有让会话保持打开状态,但实体停留在一级或二级缓存中。
    • @Michael J. Lee:一级缓存随着 Hibernate 会话而死。二级缓存的使用频率较低,所以我认为 OP 会提到他或她是否正在使用它。
    • 谢谢,你是对的。我应该说查询缓存而不是一级缓存。 (为你+1!)
    • 是的。我看到问题已被编辑以包含 openSessionInViewInterceptor...
    • @Olaf - 我在上面包含了我的 spring/hibernate 配置。我尝试将 TransactionProxyFactoryBean 用于事务管理器的设置。这将允许我避免使用“beginTransaction”、“closeTransaction”,并使用 finally 检查关闭。它将事务与 java 线程本身联系起来。我认为我的问题是我没有正确检索新交易。我认为 Michael J. Lee 的想法是正确的。但是我需要检索一个与我的 spring/quartz 批处理调用相关的新事务实例,我认为通过显式调用应用程序上下文。
    猜你喜欢
    • 2017-10-06
    • 1970-01-01
    • 2010-09-14
    • 2010-10-29
    • 2021-08-09
    • 2011-07-14
    • 1970-01-01
    • 1970-01-01
    • 2014-07-14
    相关资源
    最近更新 更多