我使用Spring 1.5.9和spring starter jpa和Camel 2.20.1。作为输入,我得到一个包含一系列元素的XML文件,我用JAXB解除了它的封送,然后我将它们聚合到一个元素列表中。
为此,我定义了一个元素类,其中我将JAXB的根元素关联起来,并将其注释为JPA实体。
@Entity
@Table (name="tblElement", schema="comp")
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Element implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long id;
@Column (name="name")
@XmlElement(required = true)
private String name;
public void Element(){}
//getter and setter methods
...
} 因此,我的骆驼路由处理了一个条目列表,我想将这些条目存储到一个MySQL数据库(版本: 5.1.73)。
@Component
public class CompRoute extends RouteBuilder {
@Autowired
private ElementDao elementDao;
@Override
public void configure() throws Exception {
DataFormat jaxbDataFormat = new JaxbDataFormat("com.comp.beans");
from(file:src/test/resources/input)
.convertBodyTo(byte[].class, "UTF-8")
.split().tokenizeXML("element")
.unmarshal(jaxbDataFormat)
.setProperty("SplitSize", simple("${header.CamelSplitSize}"))
.aggregate(constant(true), new ArrayListAggregationStrategy())
.completionSize(simple("${property.SplitSize}"))
.bean(elementDao, "insertElementList");
}
}我不太熟悉JPA和事务管理器,因此我根据以下文档对其进行了配置:
https://spring.io/guides/gs/accessing-data-jpa/
https://docs.spring.io/spring-data/jpa/docs/1.5.0.RELEASE/reference/html/jpa.repositories.html
application.properties
spring.datasource.url=jdbc:mysql://compserver:3306/comp
spring.datasource.username=user
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.jdbc.Driver JpaConfig.java
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackageClasses = CompApplication.class)
class JpaConfig {
@Autowired
DataSource dataSource;
@Bean
public EntityManagerFactory entityManagerFactory() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(false);
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
String entities = ClassUtils.getPackageName(CompApplication.class);
factory.setPackagesToScan(entities);
factory.setDataSource(dataSource);
factory.afterPropertiesSet();
return factory.getObject();
}
@Bean
@Qualifier (value = "jpaTransactionManager")
public PlatformTransactionManager transactionManager() {
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(entityManagerFactory());
return txManager;
}
}CompApplication.java
@SpringBootApplication
public class CompApplication {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(CompApplication.class);
app.setBannerMode(Banner.Mode.OFF);
app.run(args);
}}
ElementDao.java
@Service
public class ElementDao {
@Autowired
ElementRepository elementRepository;
@Transactional (transactionManager = "jpaTransactionManager", readOnly = false, propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
public void insertElementList(Exchange exchange) {
if(exchange.getIn().getBody() instanceof List) {
List<Element> elements= convertListToElementList(exchange.getIn().getBody(List.class));
if (elements != null) {
elementRepository.save(elements);
}
}
}
}ElementRepository.java
@Repository
public interface ElementRepository extends CrudRepository<Element, Long> {
}但是我的事务配置不正确。因为如果出现错误,例如在存储第5个元素时发生错误,则整个事务不会回滚。它不应插入任何元素。但是,前4个元素仍然被存储和执行。
我不明白这种行为?如何将整个操作在数据库存储期间发生异常时回滚的服务#插入元素列表事务性设置为?
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.company</groupId>
<artifactId>company</artifactId>
<version>0.0.1</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<camel.version>2.20.1</camel.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jdbc</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.45</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jaxb</artifactId>
<version>2.20.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-artemis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jms</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>com.ibm</groupId>
<artifactId>com.ibm.mq.allclient</artifactId>
<version>9.0.0.1</version>
</dependency>
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>4.8</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.1.8</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
</dependencies>
</project>发布于 2017-12-06 15:02:54
我找到了解决办法。问题是数据库而不是我的配置。MySql表的类型为MyISAM,它不支持事务和回滚。因此,我将表转换为InnoDB,现在它可以工作了--当事务失败时,所有内容都回滚。
发布于 2017-12-04 11:45:50
根据Spring文档。
@Transactional在它定义的应用程序上下文中。这意味着,如果您在WebApplicationContext中为一个DispatcherServlet添加注释,它只检查控制器中的@Transactional,而不是您的服务。
因此,您的保存方法不是事务性的,请包含定义了保存方法的包。
https://stackoverflow.com/questions/47631207
复制相似问题