【问题标题】:Transactional annotation not working in Spring Boot with jpa事务注释在带有 jpa 的 Spring Boot 中不起作用
【发布时间】:2018-03-22 14:55:16
【问题描述】:

我在我的项目中使用带有 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

如何正确使用事务或配置

【问题讨论】:

    标签: java mysql spring jpa


    【解决方案1】:

    正如@Kenny Tai Huynh 所说,我建议您将事务移至服务层(不过这取决于您)。 无论如何,由于方法可见性,@Transactional 可能没有被选中...尝试将其更改为 public 并检查它是否有效

    【讨论】:

    • 要添加到这个答案,我试过了,它仍然无法正常工作。我可以在调试方法时在数据库中选择新条目(因此事务不应该被提交,也不应该有结果)。不过,为我解决的问题是在类级别而不是方法级别使用 @Transaction 注释。我没有将其添加为答案,因为我仍然不能完全确定这是否是一个好主意。
    【解决方案2】:

    谢谢大家,我将方法 saveProduct 设置为 public。它正在工作。 @Transactional(rollbackFor = TestException.class)注解应该放在Controller还是Service上没有要求

    服务:

    @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;
        }
    
    }
    

    【讨论】:

      【解决方案3】:

      虽然 EJB 容器的默认行为是让 EJB 容器在系统异常(通常是运行时异常)上自动回滚事务,但 EJB CMT 不会在应用程序异常(即检查异常)上自动回滚事务除了 java.rmi.RemoteException)。虽然声明式事务管理的 Spring 默认行为遵循 EJB 约定(回滚仅在未检查的异常上自动),但自定义它通常很有用。

      在下一页很好地解释了

      https://www.catalysts.cc/en/wissenswertes/spring-transactional-rollback-on-checked-exceptions/

      【讨论】:

      【解决方案4】:

      @Transactional 不应在 Controller 中。只有应用程序中的服务层识别数据库/业务事务的范围。你能把代码移到@Service 类,然后再试一次吗?!

      【讨论】:

      • 我将代码移至@Service 类,并且我还使用@Transactional (rollbackFor = TestException.class)。没有效果
      猜你喜欢
      • 2015-09-01
      • 2019-07-15
      • 1970-01-01
      • 2019-06-15
      • 2018-12-30
      • 1970-01-01
      • 2015-05-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多