Announcement Announcement Module
Collapse
No announcement yet.
HibernateTemplate and EntityInterceptor Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • HibernateTemplate and EntityInterceptor

    I'm using springframework 1.1 with hibernate 2.1.6. Using the
    configuration below, it seems that my HibernateTemplate.saveOrUpdate() is not working with hibernate interceptor, Also hibernate interceptor is not
    used at hibernate session creation.

    Here is an excerpt from my applicationContext.xml file:
    <!-- interceptor to free temperary clob/blob resource-->
    <bean id="lobCleanUpInterceptor" class="com.xxx.util.LobCleanUpInterceptor" />

    <!-- Transaction manager for a single Hibernate SessionFactory (alternative to JTA) -->
    <!-- Hibernate Transaction Manager -->
    <bean id="myTransactionManager" class="org.springframework.orm.hibernate.Hibernate TransactionManager">
    <property name="sessionFactory">
    <ref local="mySessionFactory"/>
    </property>
    <property name="entityInterceptor">
    <ref local="lobCleanUpInterceptor"/>
    </property>
    </bean>

    In my DAO implementation:
    public void updateProcess (Object dp) {
    Interceptor e = getHibernateTemplate().getEntityInterceptor();
    getHibernateTemplate().saveOrUpdate(dp); // does not update fields.
    }

    The Interceptor e is null and saveOrUpdate does not update the values??

    Not sure what is happening.. Any help is appreciated.

  • #2
    You need to actually wrap your service layer methods (preferably you wrap your service layer as opposed to your actual DAOs) transactionally, using TransactionProxyFactoryBean or BeanNameAutoProxyCreator. Please take a look at the samples that come with Spring, along with the manual. There's also a number of threads here that show sample configs.

    Comment


    • #3
      Yes, I do use TransactionProxyFactoryBean for transactions in the service layer..

      <!-- Transaction manager for a single Hibernate SessionFactory (alternative to JTA) -->
      <!-- Hibernate Transaction Manager -->
      <bean id="myTransactionManager" class="org.springframework.orm.hibernate.Hibernate TransactionManager">
      <property name="sessionFactory">
      <ref local="mySessionFactory"/>
      </property>
      <property name="entityInterceptor">
      <ref local="lobCleanUpInterceptor"/>
      </property>
      </bean>

      <!-- Transaction Proxy Template -->
      <bean id="txProxyTemplate" lazy-init="true"
      class="org.springframework.transaction.interceptor .TransactionProxyFactoryBean">
      <property name="transactionManager">
      <ref local="myTransactionManager"/>
      </property>
      <property name="transactionAttributes">
      <props>
      <prop key="*">PROPAGATION_REQUIRED</prop>
      </props>
      </property>
      </bean>

      <!-- service -->
      <bean id="myDataProcessFlowService" parent="txProxyTemplate" >
      <property name="target">
      <bean class="com.xxx.DataProcessFlowServiceImpl"></bean>
      </property>
      <property name="transactionAttributes">
      <props>
      <prop key="save*">PROPAGATION_REQUIRED,-Exception</prop>
      <prop key="insert*">PROPAGATION_REQUIRED,-Exception</prop>
      <prop key="update*">PROPAGATION_REQUIRED,-Exception</prop>
      </props>
      </property>
      </bean>

      Comment


      • #4
        Re: HibernateTemplate and EntityInterceptor

        Originally posted by springuser

        Code:
            <!-- Transaction manager for a single Hibernate SessionFactory &#40;alternative to JTA&#41; -->
            <!-- Hibernate Transaction Manager -->
            <bean id="myTransactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager">
                <property name="sessionFactory">
                    <ref local="mySessionFactory"/>
                </property>
                <property name="entityInterceptor">
                   <ref local="lobCleanUpInterceptor"/>
                </property>
            </bean>
        
        In my DAO implementation&#58;
        public void updateProcess &#40;Object dp&#41; &#123;
                Interceptor e =  getHibernateTemplate&#40;&#41;.getEntityInterceptor&#40;&#41;;
                getHibernateTemplate&#40;&#41;.saveOrUpdate&#40;dp&#41;; // does not update fields.
            &#125;
        The Interceptor e is null and saveOrUpdate does not update the values??

        Not sure what is happening.. Any help is appreciated.
        It's normal for the HibernateTemplate.getEntityInterceptor() method to return null, since you are not actually setting the entity interceptor via the template. The template knows nothing about the entity interceptor, and doesn't have to. You're setting it via the HibernateTranactionManager (and the latter is indeed the best place to set Session based entity interceptors. SessionFactory is the best place to set SessionFactory based entity interceptors).

        As for the update operation not updating values, it's hard to say what is going on based on the iinfo you've given. This is LOB fields, regular fields, cascaded collections?

        Comment


        • #5
          Yes, they are regular date fields updating the Oracle 9 database. The HibernateTemplate.SaveOrUpdate works fine if I take out this interceptor entry. It seems that the HibernateTemplate constructor does not call
          setEntityInterceptor? Or should I do it myself?

          Is it a bug or is it something that I should do and that I don't?


          The LobInterceptor code looks like this:

          public class LobCleanUpInterceptor implements Interceptor {
          private static final Logger logger = Logger
          .getLogger(LobCleanUpInterceptor.class);


          // a thread local set to store temperary LOBs
          private static final ThreadLocal threadTempLobs
          = new ThreadLocal();

          // after flush(), clean all registered LOBs
          public void postFlush(Iterator entities)
          throws CallbackException {
          Set tempLobs = (Set) threadTempLobs.get();
          if (tempLobs == null) {
          return;
          }
          try {
          for (Iterator iter = tempLobs.iterator(); iter.hasNext() {
          Object lob = iter.next();
          //use reflection
          Method freeTemporary = lob.getClass().getMethod("freeTemporary", new Class[0]);
          freeTemporary.invoke(lob, new Object[0]);

          //cleanIfBLOB(lob);
          //cleanIfCLOB(lob);
          }
          /* } catch (SQLException e) {
          logger.fatal("clean LOB failed" + e.getMessage(), e);
          throw new RuntimeException(e);*/
          } catch (NoSuchMethodException e) {
          // could not find the metho with reflection
          throw new RuntimeException("Unable to find a required method.\n" + e.getMessage());
          } catch (IllegalAccessException e) {
          throw new RuntimeException("Unable to access a required method or field.\n" + e.getMessage());
          } catch (InvocationTargetException e) {
          throw new RuntimeException(e.getMessage());
          } finally {
          threadTempLobs.set(null);
          tempLobs.clear();
          }
          }

          public Boolean isUnsaved(Object o) {
          return null; //To change body of implemented methods use File | Settings | File Templates.
          }

          public int[] findDirty(Object o, Serializable serializable, Object[] objects, Object[] objects1, String[] strings, Type[] types) {
          return new int[0]; //To change body of implemented methods use File | Settings | File Templates.
          }

          public Object instantiate(Class aClass, Serializable serializable) throws CallbackException {
          return null; //To change body of implemented methods use File | Settings | File Templates.
          }

          // free temperary clob resource
          private static void cleanIfCLOB(Object lob)
          throws SQLException {
          if (lob instanceof oracle.sql.CLOB) {
          oracle.sql.CLOB clob = (oracle.sql.CLOB) lob;
          if (clob.isTemporary()) {
          oracle.sql.CLOB.freeTemporary(clob);
          logger.info("clob cleaned");
          }
          }
          }

          // free temperary blob resource
          private static void cleanIfBLOB(Object lob)
          throws SQLException {
          if (lob instanceof oracle.sql.BLOB) {
          oracle.sql.BLOB blob = (oracle.sql.BLOB) lob;
          if (blob.isTemporary()) {
          oracle.sql.BLOB.freeTemporary(blob);
          logger.info("blob cleaned");
          }
          }
          }

          // register oracle temperary BLOB/CLOB into
          // a thread-local set, this should be called at
          // the end of nullSafeSet(...) in BinaryBlobType
          // or StringClobType
          public static void registerTempLobs(Object lob) {
          getTempLobs().add(lob);
          }

          // lazy create temperary lob storage
          public static Set getTempLobs() {
          Set tempLobs = (Set) threadTempLobs.get();
          if (tempLobs == null) {
          tempLobs = new HashSet();
          threadTempLobs.set(tempLobs);
          }
          return tempLobs;
          }

          public boolean onLoad(Object o, Serializable serializable, Object[] objects, String[] strings, Type[] types) throws CallbackException {
          return false; //To change body of implemented methods use File | Settings | File Templates.
          }

          public boolean onFlushDirty(Object o, Serializable serializable, Object[] objects, Object[] objects1, String[] strings, Type[] types) throws CallbackException {
          return false; //To change body of implemented methods use File | Settings | File Templates.
          }

          public boolean onSave(Object o, Serializable serializable, Object[] objects, String[] strings, Type[] types) throws CallbackException {
          return false; //To change body of implemented methods use File | Settings | File Templates.
          }

          public void onDelete(Object o, Serializable serializable, Object[] objects, String[] strings, Type[] types) throws CallbackException {
          //To change body of implemented methods use File | Settings | File Templates.
          }

          public void preFlush(Iterator iterator) throws CallbackException {
          //To change body of implemented methods use File | Settings | File Templates.
          }
          }

          Comment


          • #6
            You missed my point. You are setting the entity interceptor at the HibernateTransactionManager level, which is fine. It will trigger setting it on the session when the session is created as a result of entering a transaction. There is no need for the template to get involved in setting the interceptor.

            Now what may be happening is that in fact, you are not really running transactionally (look in your logs to see if new transactions are being created). If you are not in a transaction when the template is called, then there will be no pre-existing thread-bound session (associated with the transaction), and one will be triggered to be created right then. In that case, there will be no interceptor. But you want to be running transacitonally there in any case, so that's an error in declaring your transactional pointcuts. When using HibernateTransactionManager, I always make sure to set the allowCreate flag to false on the template, so I never have the situation of accidentally creating a session outside of a transaction like this, when all sessions should be only created by the outer wrapping transaction...

            Comment

            Working...
            X