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.