简体   繁体   中英

Understaning of @Transactional in Spring Boot - though exception changes doesn't rollback in database

I'm trying to understand @Transactional in spring - to test it I create simple project:

Model:

@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:

    @Repository
    public interface ModelRepository extends CrudRepository<Model,Long> {
    }

Service:

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

Controller:

@RestController
public class Controller {

    @Autowired
    private ExampleService exampleService;

    @GetMapping(path = "/search/{number}")
    public String search(@PathVariable Integer number){

        return exampleService.doSomething(number);
    }
}

When I go to localhost:8080/search/1 - all goes well and object is saved in database.

But when I go localhost:8080/search/10 - as I wanted - it throws Exception, but still object is saved in database.

Shouldn't be rollback here? Method which is annotated with @Transactional is public and in other bean.

Edit: 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

build.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'
}

main class:

@SpringBootApplication
public class TransactionalApplication {

    public static void main(String[] args) {
        SpringApplication.run(TransactionalApplication.class, args);
    }

}

Sample of config with spring, jpa, hibernate and 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;
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM