我過了一天半尋找答案,但這件事會讓我發瘋!@Transactional Services
我和我的隊友正在基於springboot開展一個項目。我專門研究管理部分,這是一個Web管理。
我的項目主要有三層:使用使用存儲庫的服務的控制器。 我希望我的項目能在服務層使用@Transactional(迄今爲止我們只做了一些成功的努力,只使用註釋進行配置)。
但是,它似乎不起作用:我的服務之一拋出一個RuntimeException並且沒有回滾完成。我已經閱讀了其他兄弟學科的所有主張。唯一的問題,與我的問題有關,我不確定乾淨整潔是上下文配置。 Eventhow,我不確定這是否是我的問題。
我告訴你實際的配置:
@SpringBootApplication
@EnableScheduling
@EnableTransactionManagement
public class Application extends SpringBootServletInitializer {
@Value("${ajp.port}")
private int ajpPort;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(Application.class);
}
@Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory() {};
tomcat.addAdditionalTomcatConnectors(createConnector(ajpPort));
return tomcat;
}
@Bean
public EmbeddedServletContainerCustomizer containerCustomizer() {
return container -> {
ErrorPage error401Page = new ErrorPage(HttpStatus.UNAUTHORIZED, "/static/401.html");
ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/static/404.html");
container.addErrorPages(error401Page, error404Page);
};
}
@Bean
public EmailValidator emailValidator() {
return EmailValidator.getInstance();
}
private static Connector createConnector(int ajpPort) {
Connector connector = new Connector("AJP/1.3");
connector.setPort(ajpPort);
return connector;
}
}
web配置:
@Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
@Autowired
private RequestProcessingTimeInterceptor requestProcessingTimeInterceptor;
@Autowired
private CertificateInterceptor certificateInterceptor;
@Autowired
private ProfilesAuthorizationInterceptor profilesAuthorizationInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(requestProcessingTimeInterceptor);
registry.addInterceptor(certificateInterceptor);
registry.addInterceptor(profilesAuthorizationInterceptor);
}
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
@Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setExposeContextBeansAsAttributes(true);
resolver.setPrefix("/WEB-INF/");
resolver.setSuffix(".jsp");
return resolver;
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/admin/css/**").addResourceLocations("/WEB-INF/admin/css/").setCachePeriod(CACHE_PERIOD);
registry.addResourceHandler("/admin/img/**").addResourceLocations("/WEB-INF/admin/img/").setCachePeriod(CACHE_PERIOD);
registry.addResourceHandler("/admin/js/**").addResourceLocations("/WEB-INF/admin/js/").setCachePeriod(CACHE_PERIOD);
registry.addResourceHandler("/admin/plugins/**").addResourceLocations("/WEB-INF/admin/plugins/").setCachePeriod(CACHE_PERIOD);
}
}
一個控制器上的樣:
@RestController
@RequestMapping("/pathA")
public class ControlerA {
@Autowired
public ServiceA serviceA;
@RequestMapping(value = "{id}", method = RequestMethod.GET)
@ResponseStatus(HttpStatus.OK)
public A getA(@PathVariable long id) {
return serviceA.getA(id);
}
}
A服務類(接口+實現) :
public interface ServiceA {
A getA(long id);
}
@Service
@Transactional
public class ServiceAImpl implements ServiceA {
@Autowired
public RepositoryA repositoryA;
public A getA(long id) {
(...)
A a = repositoryA.findOne(id);
a.updatesomething(something);
repositoryA.update(a);
doOtherThing(a); //throw RuntimeException
(...)
return a;
}
}
和知識庫:
@Repository
public interface RepositoryA extends JpaRepository<A, Long> {
(...)
}
這裏是MySQL數據庫的配置:
# Configuration de la base de donnée
spring.datasource.url=jdbc:mysql://localhost/name_innodb
spring.datasource.username=username
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.testOnBorrow=true
spring.datasource.validationQuery=SELECT 1
我知道倉庫交易工作在默認情況下(我看到了它,當SQLException的發生)。但是在服務層中,沒有任何事情發生(參見拋出異常行)。當拋出異常時,更新完成而不是回滾。那麼這意味着我的@Transactional被忽略。
編輯: 我設法讓像我想要一個交易,在控制器的方法getA(...)
加入@Transactional。它可以工作,但它不是管理交易的地方。
然後我的問題是:我如何使它工作?
哪個數據庫?顯示你的配置(屬性等)。另外你使用的是Spring Boot,那麼爲什麼你需要一個Web配置類(Spring引導已經配置好了) –
最初的配置不是來自我,我認爲配置的分離是爲了更好的可讀性。 ... – Mohicane
你不需要這樣的配置,因爲spring boot已經爲你配置了MVC,你的實際服務方法還是你有一個try/catch塊或者其他東西?如果@ Transactional沒有工作 –