簡體   English   中英

事務注釋在使用jpa的Spring Boot中不起作用

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM