पर नेस्टेड लेनदेन ने नेस्टेड स्प्रिंग लेनदेन का उपयोग करते समय मुझे कुछ अजीब व्यवहार मिला: जब, उसी कक्षा में, @Transactional
के रूप में एनोटेटेड विधि को @Transactional
के रूप में भी एनोटेट किया गया दूसरा एनोटेशन का उपयोग नहीं किया जाता है।वसंत
के निम्नलिखित वर्ग पर ध्यान दें:
public class Main {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
final Main main = context.getBean(Main.class);
// First Op
System.out.println("Single insert: " + main.singleInsert());
// Second Op
main.batchInsert();
// Third Op
main.noTransBatchInsert();
}
@PersistenceContext
private EntityManager pm;
@Transactional(propagation=Propagation.REQUIRED)
public void batchInsert() {
System.out.println("batchInsert");
System.out.println("First insert: " + singleInsert());
System.out.println("Second insert: " + singleInsert());
}
public void noTransBatchInsert() {
System.out.println("noTransBatchInsert");
System.out.println("First insert: " + singleInsert());
System.out.println("Second insert: " + singleInsert());
}
@Transactional(propagation=Propagation.REQUIRES_NEW)
public int singleInsert() {
System.out.println("singleInsert");
Pojo p = new Pojo();
pm.persist(p);
return p.getId();
}
}
इकाई यदि निम्न वर्ग:
@Entity
public class Pojo {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
@Override
public String toString() {
return "Pojo: " + id;
}
public int getId() {
return id;
}
}
और स्ट्रिंग भागों applicationContext.xml:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
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/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd">
<tx:annotation-driven />
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="MyPersistenceUnit" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
</beans>
और विन्यास वर्ग (मैं इसे applicationContext.xml में विलय कर सकता था)।
@Configuration
@ImportResource("/META-INF/applicationContext.xml")
public class Config {
@Bean
public Main main() {
return new Main();
}
}
पूर्णता के लिए persistence.xml फ़ाइल:
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0">
<persistence-unit name="MyPersistenceUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.hbm2ddl.auto" value="create" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
<property name="hibernate.connection.driver_class" value="org.h2.Driver" />
<property name="hibernate.connection.url" value="jdbc:h2:mem:TestDSJPA2;DB_CLOSE_DELAY=-1;LOCK_MODE=0" />
<!--<property name="hibernate.connection.url" value="jdbc:h2:mem:TestDSJPA2;DB_CLOSE_DELAY=-1;LOCK_MODE=0" />-->
<property name="hibernate.connection.username" value="sa" />
<property name="hibernate.connection.password" value="" />
<property name="hibernate.connection.autocommit" value="false"/>
<property name="hibernate.c3p0.min_size" value="5" />
<property name="hibernate.c3p0.max_size" value="20" />
<property name="hibernate.c3p0.timeout" value="300" />
<property name="hibernate.c3p0.max_statements" value="50" />
<property name="hibernate.c3p0.idle_test_period" value="3000" />
</properties>
</persistence-unit>
</persistence>
तो मुख्य वर्ग में, पहला ऑपरेशन के रूप में की उम्मीद है कि एक नए सौदे में है किया जाता है। (कुछ डीबग संदेशों सहित) उत्पादन होता है:
DEBUG o.h.transaction.JDBCTransaction - begin
singleInsert
DEBUG o.h.transaction.JDBCTransaction - commit
Single insert: 1
दूसरे ऑपरेशन के बाद उत्पादन देता है:
batchInsert
singleInsert
DEBUG o.h.transaction.JDBCTransaction - begin
First insert: 2
singleInsert
Second insert: 3
DEBUG
यह नहीं है कि मैं क्या उम्मीद के बाद से @Transactional(propagation=Propagation.REQUIRES_NEW)
साथ singleInsert व्याख्या में मैं एक नया लेनदेन उम्मीद करेंगे प्रत्येक कॉल के लिए बनाया जाना चाहिए जो कि नहीं हो रहा है क्योंकि एक ही शीर्ष स्तर लेनदेन दोनों प्रविष्टियों के लिए उपयोग किया जाता है।
तीसरे आपरेशन के साथ-साथ कोई लेन-देन बिल्कुल बनाई गई है विफल रहता है:
noTransBatchInsert
singleInsert
DEBUG o.h.e.def.AbstractSaveEventListener - delaying identity-insert due to no transaction in progress
First insert: 0
singleInsert
DEBUG o.h.e.def.AbstractSaveEventListener - delaying identity-insert due to no transaction in progress
Second insert: 0
@Configuration
सेम स्प्रिंग सुनिश्चित है कि एक ही कक्षा proxified कर रहे हैं जो स्पष्ट रूप से है यहाँ नहीं हो रहा पर विधि करने के लिए कॉल में। क्या इस व्यवहार को बदलने का कोई तरीका है?