我正在测试这种情况,当我从Thread调用委托方法时,spring transaction不会开始。 但是,当我直接调用委托方法时,它完美地工作。任何人都可以建议这里缺少什么..?
这是我的主要课程:
@Component
public class SpringMainApplication {
@Autowired
private InsertThread insertThread;
@Autowired
private PrintThread printThread;
@Autowired
private ThreadPoolTaskExecutor taskExecutor;
public void startApplication() {
taskExecutor.execute(insertThread);
taskExecutor.execute(printThread);
/*This works
int count =1;
while(count<=4) {
count ++;
Employee empBean = new Employee();
empBean.setAddress("ADD");
empBean.setName("NAME");
empDelegate.insertElement(empBean );
}*/
}
}
我的线程类:插入线程并打印线程以插入元素并从DB中检索元素。我在这里使用MYSQL
package com.sap.springconcurrent.thread;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.sap.springconcurrent.bean.Employee;
import com.sap.springconcurrent.bean.TestBean;
import com.sap.springconcurrent.delegate.EmployeeDelegate;
@Service
public abstract class InsertThread extends Thread{
@Autowired
EmployeeDelegate empDelegate;
public InsertThread(EmployeeDelegate empDelegate) {
this.empDelegate = empDelegate;
}
@Override
public void run() {
System.out.println("Count"+ empDelegate.getCount());
while(empDelegate.getCount() <= 5){
synchronized (empDelegate) {
Employee emp = new Employee();
emp.setName(createTestBean().getTestValue());
emp.setAddress("Address");
System.out.println("Insert"+ empDelegate.getCount() +1 );
empDelegate.insertElement(emp);
}
}
}
protected abstract TestBean createTestBean();
}
package com.sap.springconcurrent.thread;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import com.sap.springconcurrent.bean.TestBean;
import com.sap.springconcurrent.delegate.EmployeeDelegate;
@Service
@Scope("singleton")
public class PrintThread extends Thread {
@Autowired
TestBean testBean;
@Autowired
EmployeeDelegate empDelegate;
public PrintThread(EmployeeDelegate empDelegate) {
this.empDelegate = empDelegate;
}
@Override
public void run() {
while (empDelegate.getCount() <= 10) {
synchronized (empDelegate) {
empDelegate.retrieveElement(testBean.getTestValue());
}
}
}
}
我的bean来自这里我称之为处理交易的DAO
package com.sap.springconcurrent.delegate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import com.sap.springconcurrent.bean.Employee;
import com.sap.springconcurrent.dao.EmployeeDao;
@Service
@Scope("singleton")
public class EmployeeDelegate {
@Autowired
EmployeeDao doa;
private boolean elementRetreived = true;
private int count = 0;
public void insertElement(Employee empBean) {
System.out.println("Insert Start");
while (!elementRetreived) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
count++;
empBean.setName(empBean.getName() + count);
empBean.setAddress(empBean.getAddress() + count);
System.out.println("Calling DAo");
Employee emp = saveEmp(empBean);
System.out.println("Inserted Employee" + emp.toString());
elementRetreived = false;
notifyAll();
}
//@Transactional(propagation=Propagation.REQUIRED)
public Employee saveEmp(Employee empBean) {
return doa.save(empBean);
}
public void retrieveElement(String name) {
while (elementRetreived) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Employee emp = doa.getEmployeeWithName(name + count);
System.out.println("Retrieved Employee" + emp.toString());
elementRetreived = true;
notifyAll();
}
public boolean isElementRetreived() {
return elementRetreived;
}
public int getCount() {
return count;
}
}
我的道: 这是交易制作
package com.sap.springconcurrent.dao;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.sap.springconcurrent.bean.Employee;
@Repository
@Transactional(propagation = Propagation.REQUIRES_NEW)
public class EmployeeDao {
@PersistenceContext
EntityManager entityManagerFactory;
@Transactional(propagation = Propagation.REQUIRES_NEW)
public Employee save(Employee employee) {
System.out.println("Insertint");
entityManagerFactory.persist(employee);
return employee;
}
@Transactional(readOnly=true)
public Employee getEmployeeWithName(String empName) {
String query = "select emp from Employee emp where emp.name LIKE :name ";
Query q = entityManagerFactory.createQuery(query);
q.setParameter("name", empName);
return (Employee) q.getResultList().get(0);
}
}
Spring COnfig :
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<context:component-scan base-package="com.sap.springconcurrent" />
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="testBean" class="com.sap.springconcurrent.bean.TestBean"
scope="prototype">
<property name="testValue" value="testValue"></property>
</bean>
<bean class="org.springframework.orm.jpa.JpaTransactionManager"
id="transactionManager" scope="prototype">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<bean id="empDelegate" class="com.sap.springconcurrent.delegate.EmployeeDelegate">
</bean>
<bean id="insertThread" class="com.sap.springconcurrent.thread.InsertThread"
scope="prototype">
<constructor-arg ref="empDelegate" />
<lookup-method name="createTestBean" bean="testBean" />
</bean>
<bean id="printThread" class="com.sap.springconcurrent.thread.PrintThread"
scope="prototype">
<constructor-arg ref="empDelegate" />
</bean>
<bean id="taskExecutor"
class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="5" />
<property name="maxPoolSize" value="10" />
<property name="WaitForTasksToCompleteOnShutdown" value="true" />
</bean>
<bean name="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/mytestdb" />
<property name="username" value="root" />
<property name="password" value="saplab" />
</bean>
<bean id='entityManagerFactory'
class='org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean'>
<property name="persistenceUnitName" value="testPersistenceUnit" />
<property name="packagesToScan" value="com.sap.springconcurrent.bean.Employee" />
<property name='dataSource' ref='dataSource' />
<property name="jpaVendorAdapter">
<bean
class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="generateDdl" value="true" />
<property name="databasePlatform"
value="org.eclipse.persistence.platform.database.MySQLPlatform" />
</bean>
</property>
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaDialect" />
</property>
<property name="jpaPropertyMap">
<map>
<entry key="eclipselink.weaving" value="false" />
</map>
</property>
</bean>
</beans>
persistence Xml :
<?xml version="1.0" encoding="UTF-8"?>
<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" xmlns="http://java.sun.com/xml/ns/persistence">
<persistence-unit name="driftsloggPersistenceUnit" transaction-type="RESOURCE_LOCAL">
<provider>
org.eclipse.persistence.jpa.PersistenceProvider
</provider>
<class>com.sap.springconcurrent.bean.Employee</class>
<properties>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/mytestdb" />
<property name="javax.persistence.jdbc.user" value="root" />
<property name="javax.persistence.jdbc.password" value="saplab" />
<!-- EclipseLink should create the database schema automatically -->
<property name="eclipselink.ddl-generation" value="create-tables" />
<property name="eclipselink.ddl-generation.output-mode" value="database" />
</properties>
</persistence-unit>
</persistence>
My Start :
package com.sap.springconcurrent.main;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@ContextConfiguration(locations = "classpath:spring-config.xml")
@RunWith(SpringJUnit4ClassRunner.class)
public class SpringMainApplicationTest {
@Autowired
SpringMainApplication app;
@Test
public void test() {
app.startApplication();
}
}