![](/img/trans.png)
[英]Spring Boot + JPA : @Transactional annotation : Roll back is not working
[英]Transactional annotation not working in Spring Boot with jpa
我在我的項目中使用帶有jpa,mysql的Spring boot。 但是@Transaction無法正常工作。 如果下面給出任何錯誤代碼,它不會回滾所有數據。 有什么建議么? 謝謝。
應用:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
實體產品:
@Entity
public class Product extends BaseModel<Long> {
@Id
@GeneratedValue
private Long id;
private String description;
@OneToMany(mappedBy = "productId", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<Speed> speeds;
//geter and seter
}
實體速度:
@Entity
public class Speed extends BaseModel<Long> {
@Id
@GeneratedValue
private Long id;
private Long productId;
private Long productSpeed;
//Getter and setter
}
倉庫:
public interface SpeedRepository extends JpaRepository<Speed, Long> {
}
public interface ProductRepository extends JpaRepository<Product, Long> {
}
服務:
@Service
public class ProductService {
@Autowired
private ProductRepository productRepository;
@Autowired
private speedRepository speedRepository;
@Transactional(rollbackFor = TestException.class)
void saveProduct(Product product) throws TestException {
try{
productRepository.save(product);
for (Speed speed : product.getSpeeds()) {
speedRepository.save(speed);
}
} catch (TestException e) {
throw new TestException("error", "error message");
}
}
}
控制器:
@RestController
@RequestMapping("/product")
public class ProductRestController {
@Autowired
private ProductRepository productRepository;
@Autowired
private MachineSpeedRepository machineSpeedRepository;
@Autowired
private ProductService productService;
@RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
Object addListProduct(OAuth2Authentication auth, @RequestBody Product product) throws TestException {
productService.saveProduct(product);
return product;
}
}
application.properties:
spring.jpa.hibernate.ddl-auto=none
spring.datasource.url=jdbc:mysql://192.168.1.111/test?useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
build.gradle:
buildscript {
ext {
springBootVersion = '1.5.6.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
compile("org.springframework.security.oauth:spring-security-oauth2")
compile("org.springframework.boot:spring-boot-starter-web")
compile("org.hibernate:hibernate-validator")
compile 'org.springframework.boot:spring-boot-starter-data-jpa'
compile 'mysql:mysql-connector-java'
testCompile('org.springframework.boot:spring-boot-starter-test')
}
數據庫:
CREATE TABLE `product` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`description` text NOT NULL COMMENT 'product name',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=utf8
CREATE TABLE `speed` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`product_id` bigint(20) DEFAULT NULL,
`product_speed` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=25 DEFAULT CHARSET=utf8
我如何使用交易或正確配置
盡管EJB的默認行為是使EJB容器根據系統異常(通常是運行時異常)自動回滾事務,但是EJB CMT不會根據應用程序異常(即Java以外的已檢查異常)自動回滾事務。 .rmi.RemoteException)。 盡管Spring聲明式事務管理的默認行為遵循EJB約定(僅針對未檢查的異常會自動回滾),但是自定義它通常很有用。
在下一頁中很好地解釋了
https://www.catalysts.cc/en/wissenswertes/spring-transactional-rollback-on-checked-exceptions/
正如@Kenny Tai Huynh所說,我建議您將事務移至服務層(不過這取決於您)。 無論如何,由於方法可見性,可能未拾取@Transactional ...嘗試將其更改為public並檢查其是否有效
謝謝,我將方法saveProduct設置為公共。 工作正常 不需要@Transactional(rollbackFor = TestException.class)
批注應該在控制器上還是在服務上
服務:
@Service
public class ProductService {
@Autowired
private ProductRepository productRepository;
@Autowired
private speedRepository speedRepository;
@Transactional(rollbackFor = TestException.class)
public void saveProduct(Product product) throws TestException {
try{
productRepository.save(product);
for (Speed speed : product.getSpeeds()) {
speedRepository.save(speed);
}
} catch (TestException e) {
throw new TestException("error", "error message");
}
}
}
控制器:
@RestController
@RequestMapping("/product")
public class ProductRestController {
@Autowired
private ProductRepository productRepository;
@Autowired
private MachineSpeedRepository machineSpeedRepository;
@Autowired
private ProductService productService;
@RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
Object addListProduct(OAuth2Authentication auth, @RequestBody Product product) throws TestException {
productService.saveProduct(product);
return product;
}
}
@Transactional
不應位於Controller中。 只有應用程序中的服務層才能確定數據庫/業務交易的范圍。 您可以將代碼移到@Service
類,然后重試嗎?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.