java - 在 Spring Boot 中理解 @Transactional - 尽管异常更改不会在数据库中回滚
问题描述
我试图在春天理解@Transactional - 为了测试它,我创建了一个简单的项目:
模型:
@Entity
public class Model {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
String name;
Integer age;
public Model(String name, Integer age) {
this.name = name;
this.age = age;
}
}
存储库:
@Repository
public interface ModelRepository extends CrudRepository<Model,Long> {
}
服务:
@Service
public class ExampleService {
@Autowired
private ModelRepository modelRepository;
@Transactional
public String doSomething(Integer number) {
Model test = modelRepository.save(new Model("test", number));
if(number>4) throw new RuntimeException();
return test.name;
}
}
控制器:
@RestController
public class Controller {
@Autowired
private ExampleService exampleService;
@GetMapping(path = "/search/{number}")
public String search(@PathVariable Integer number){
return exampleService.doSomething(number);
}
}
当我去localhost:8080/search/1 - 一切顺利,对象保存在数据库中。
但是当我去localhost:8080/search/10 - 如我所愿 - 它抛出异常,但对象仍然保存在数据库中。
不应该在这里回滚吗?使用 @Transactional 注释的方法是公共的并且在其他 bean 中。
编辑:application.properties:
spring.datasource.url=jdbc:mysql://localhost:3306/testtt?createDatabaseIfNotExist=true&useSSL=false&serverTimezone=Europe/Paris
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.hibernate.ddl-auto=update
构建.gradle:
plugins {
id 'org.springframework.boot' version '2.1.7.RELEASE'
id 'java'
}
apply plugin: 'io.spring.dependency-management'
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '12'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
compile 'org.springframework.boot:spring-boot-starter-data-jpa'
compile 'mysql:mysql-connector-java'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
主类:
@SpringBootApplication
public class TransactionalApplication {
public static void main(String[] args) {
SpringApplication.run(TransactionalApplication.class, args);
}
}
解决方案
spring、jpa、hibernate 和 c3p0 的配置示例。
@Configuration
@ComponentScan("com.company")
@EnableTransactionManagement
public class PersistenceConfig {
@Value("${hibernate.showSql}")
private boolean showSql;
@Bean
@Primary
@ConfigurationProperties("c3p0.named-configs.pool")
@Qualifier("myDataSource")
public DataSource myDataSource() {
return new ComboPooledDataSource();
}
@Bean
public PlatformTransactionManager esTransactionManager(@Qualifier("em") EntityManagerFactory em) {
JpaTransactionManager transactionManager = new JpaTransactionManager(em);
return transactionManager;
}
@Bean
public LocalContainerEntityManagerFactoryBean em(@Qualifier("myDataSource") DataSource myDataSource, JpaVendorAdapter jpaVendorAdapter) {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setDataSource(myDataSource);
entityManagerFactoryBean.setJpaDialect(new HibernateJpaDialect());
entityManagerFactoryBean.setJpaVendorAdapter(jpaVendorAdapter);
entityManagerFactoryBean.setPersistenceUnitName("myPersistenceUnit");
entityManagerFactoryBean.setPackagesToScan("com.company");
return entityManagerFactoryBean;
}
@Bean
public JpaVendorAdapter jpaVendorAdapter(@Value("${hibernate.dialect}") String hibernateDialect,
@Value("${hibernate.showSql}") boolean showSql) {
HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
jpaVendorAdapter.setDatabasePlatform(hibernateDialect);
jpaVendorAdapter.setShowSql(showSql);
return jpaVendorAdapter;
}
}
推荐阅读
- javascript - 角项目结构?[初学者]
- javascript - 使用 sinon 提交表单时如何测试是否调用了函数?
- c# - 使用 DDE 将数据发送到 Excel 文件
- django - nginx重新启动后无法访问站点-AWS EC2
- scala - 需要帮助来修复 org.apache.hadoop.ipc.RemoteException - AWS EMR Spark Scala 应用程序
- selenium-webdriver - laravel 黄昏 facebook 网络驱动程序和 cookie
- html - 使用 GMail 发送 HTML 电子邮件时遇到问题
- python - 无法使用报纸3k 下载文章
- c# - 按依赖属性值对用户控件进行排序
- docker - 如何在dockerfile中隐藏用户并传入curl命令