Announcement Announcement Module
Collapse
No announcement yet.
How to better control transaction management when using JPAItemWriter/Hibernate? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • How to better control transaction management when using JPAItemWriter/Hibernate?

    Hi,

    I'm using Spring Batch 2.1.1 with Hibernate 3.5.3 (via JPAItemWriter) and finding that whenever Hibernate hits a deadlock, Spring Batch then throws a "JobInterruptedException" stating that the transaction is an inconsistent state and the workflow shuts down.

    It looks like the underlying cause is Hibernate forcing the transaction to roll back when it should be Spring Batch that is in charge.

    Ideally I'd love to get rid of deadlocks but ultimately they are going to happen at some point and I would like to be able to leverage the re-try template to simply try again within the same transaction. But until I can get the Spring Batch and Hibernate to play nicely together I don't see how I can do this.

    Is this a common problem with a common solution?

    Any advice would be great!

    Thanks.

  • #2
    maybe http://static.springsource.org/sprin...aseItemWriters can give you some pointers here

    the simple guideline for implementations of database* ItemWriters, is to flush on each call to write(). Doing so allows for items to be skipped reliably, with Spring Batch taking care internally of the granularity of the calls to ItemWriter after an error.
    *database is added from myself, but fits the context for the quote

    Comment


    • #3
      Can you share job configuration.

      Comment


      • #4
        Hi, below is a sample with what I believe are the pertinent config items.

        Just to add, the persistence unit definition in persistence.xml doesn't specify anything other than the beans to persist so I have not included it.

        I suspect the answer will lay in the configuration of hibernate and how to stop it interfering with the transaction but I haven't found anything in their docs to help me yet.

        Code:
        	<step
        			id="xWriter">
        			<tasklet>
        				<chunk
        					reader="xReader"
        					processor="xProcessor"
        					writer="jpaItemWriter"
        					commit-interval="1">
        				</chunk>
        				<listeners>
        					<listener
        						ref="xLoggingListener" />
        				</listeners>
        			</tasklet>
        	</step>
        
        
        	<bean
        		id="jpaItemWriter"
        		class="org.springframework.batch.item.database.JpaItemWriter">
        		<property
        			name="entityManagerFactory"
        			ref="emf" />
        	</bean>
        
        
        	<bean
        		id="jpaTemplate"
        		class="org.springframework.orm.jpa.JpaTemplate">
        		<constructor-arg>
        			<ref
        				bean="emf" />
        		</constructor-arg>
        	</bean>
        
        	<bean
        		id="transactionManager"
        		class="org.springframework.orm.jpa.JpaTransactionManager">
        		<property
        			name="entityManagerFactory"
        			ref="emf" />
        	</bean>
        
        
        
        	<bean
        		id="emf"
        		class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        		<property
        			name="dataSource"
        			ref="dataSource" />
        		<property
        			name="persistenceUnitName"
        			value="persistenceUnit" />
        		<property
        			name="jpaVendorAdapter">
        			<bean
        				class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
        				<property
        					name="showSql"
        					value="${database.showSql}" />
        			</bean>
        		</property>
        		<property
        			name="jpaProperties">
        			<props>
        				<prop key="hibernate.dialect">${database.hibernateDialect}</prop>
        				<prop key="hibernate.order_inserts">true</prop>
        				<prop key="hibernate.default_batch_fetch_size">999</prop>
        				<prop key="hibernate.jdbc.fetch_size">1000</prop>
        				<prop key="hibernate.jdbc.batch_size">500</prop>
        			</props>
        		</property>
        		<property
        			name="jpaDialect">
        			<!-- https://jira.springframework.org/browse/SPR-5012 -->
        			<bean
        				class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
        		</property>
        	</bean>
        
        	<beans:bean
        		id="jobRepository"
        		class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean"
        		p:dataSource-ref="dataSource"
        		p:transactionManager-ref="transactionManager"
        		p:isolationLevelForCreate="ISOLATION_DEFAULT"
        		p:lobHandler-ref="${database.lobHandler}" />

        Comment


        • #5
          Thanks for the advice Michael. The item writer is the "out of the box" JPAItemWriter, I would suspect that it follows the best practise but it is worth me double checking!

          Comment


          • #6
            You can add exception being thrown by Spring either in <skippable-exception-classes> element OR <retryable-exception-classes> element within the chunk element. In case of <retryable-exception-classes> also specify the retry limit. You could also combine <retryable-exception-classes> & <skippable-exception-classes> , in case you want the exception to be skipped in case retry limit is exhausted.

            Comment


            • #7
              Thanks, that all makes sense, however, the issue is that spring batch still has to commit the transaction in order to register the skip in the batch tables.
              By this point hibernate (well, I suspect it is hibernate) has interfered with the transaction so Spring batch decides that the transaction is in an unknown state, it cannot commit anything safely to the batch tables and it terminates the whole process.

              Comment


              • #8
                The exception due to the deadlock is being thrown when the chunk is being committed by Spring batch. Since commit interval is 1, Spring batch commits after each record.
                Can you test by adding exception being thrown in <skippable-exception-classes>.
                Can you also provide details/stack trace of the exception thrown ?

                Comment


                • #9
                  I will post something just as soon as I can recreate the issue. Thanks.

                  Comment

                  Working...
                  X