Spring integration: transactional method, read only flag not working
martin.ahrer Oct 27, 2008 9:19 AMI'm trying to utilize Spring managed transactions using Springs @Transactional annotation. Methods that are supposed to read data only also carry the read only flag.
In order to test that this is working I created a method that tries to break this.
It executes a entitymanager.merge() operation. Surprisingly the data is written to the database even though the method is marked read only. Just right after the merge() operation it seems that the hibernate session/persistence context is flushed. As far as I know Spring is setting the flush mode MANUAL for read only marked methods.
Also I have marked the Seam methods with flush mode MANUAL!
I'm not sure if I'm doing something fundamentally wrong. I would appreciate any hints on that!
Here is the hibernate config (from persistence.xml)
<property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver" /> <property name="hibernate.connection.username" value="sa" /> <property name="hibernate.connection.autocommit" value="false" /> <property name="hibernate.connection.url" value="jdbc:hsqldb:mem:pac" /> <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect" /> <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup" /> <property name="hibernate.hbm2ddl.auto" value="update" /> <property name="hibernate.show_sql" value="true" /> <property name="hibernate.use_sql_comments" value="true" /> <property name="hibernate.format_sql" value="true" /> <property name="hibernate.connection.default_schema" value="DBO" /> <property name="hibernate.transaction.flush_before_completion" value="false"/>
Seam is configured in components.xml
<core:init debug="true" transaction-management-enabled="false" /> <spring:context-loader config-locations="classpath:/beans/seamContext.xml" /> <persistence:managed-persistence-context name="entityManager" auto-create="true" entity-manager-factory="#{entityManagerFactorySpring}" /> <transaction:no-transaction />
So as you see Seam is not responsible for handling transactions at all!
The spring stuff is configured
<context:annotation-config /> <tx:annotation-driven proxy-target-class="true"/> <seam:configure-scopes /> <!-- The entity manager factory that will be used to hand off entity managers to Spring based components--> <bean id="entityManagerFactory" class="org.jboss.seam.ioc.spring.SeamManagedEntityManagerFactoryBean"> <property name="persistenceContextName" value="entityManager" /> </bean> <!-- The entity manager factory provided to Seam for creating a seam managed entity manager factory --> <bean id="entityManagerFactorySpring" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" p:persistenceUnitName="pac" p:persistenceProviderClass="org.hibernate.ejb.HibernatePersistence"> <property name="persistenceUnitManager"> <bean class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager"> <property name="persistenceXmlLocations" value="classpath*:META-INF/persistence.xml" /> </bean> </property> </bean> <!-- The transaction manager --> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory" /> </bean>
The seam component that invokes the transactional method looks as
@Create @Begin(flushMode = FlushModeType.MANUAL, join = false) public void create() { return; } @Conversational public String createPersonWithReadOnlyTransaction() { ... comp.saveWithReadOnlyTransaction(person); ... return "SUCCESS"; }
And the transactional method
@Transactional(readOnly=true) public Person saveWithReadOnlyTransaction(Person person) { return getJpaTemplate().merge(person); }