本文介紹了Spring Boot 2@Transaction批注使自動(dòng)連接的字段為空的處理方法,對(duì)大家解決問題具有一定的參考價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧!
問題描述
我正嘗試在我的服務(wù)的方法中使用@Transactional
注釋來延遲加載域。但是,在我的實(shí)現(xiàn)類上使用@Transactional
會(huì)使所有自動(dòng)綁定的字段null
。
以下是我的實(shí)現(xiàn):
@Service
public class UserServiceImpl implements UserService {
/**
* DefaultMapper.
*/
@Autowired
private DefaultMapper defaultMapper;
/**
* Resource service injection.
*/
@Autowired
private ResourceService resourceService;
/**
* UserRepository.
*/
@Autowired
private UserRepository userRepository;
/**
* Jwt Factory.
*/
@Autowired
private JwtService jwtService;
@Override
@Transactional
public final UserDto findByLogin(final String login) throws ResourceNotFoundException {
// user repository is null here when using @Transactional
User user = this.userRepository.findByLogin(login)
.orElseThrow(() -> new ResourceNotFoundException(
resourceService.getMessage(MessageBundle.EXCEPTION, "resource.notfound.user.login")
));
UserDto userDto = defaultMapper.asUserDtoWithRoles(user);
return userDto;
}
提前謝謝您。
推薦答案
事務(wù)是使用AOP應(yīng)用的,Spring中的默認(rèn)AOP機(jī)制是使用代理。使用Spring Boot時(shí),代理模式設(shè)置為基于類的代理。
您可以使用以下兩種方法中的一種來解決此問題。
-
從您的方法中刪除
final
通過將
spring.aop.proxy-target-class=false
添加到application.properties
來禁用基于類的代理
現(xiàn)在,當(dāng)您加載@Transactional
時(shí),這將導(dǎo)致您的UserServiceImpl
的代理被創(chuàng)建,準(zhǔn)確地說是基于類的代理。發(fā)生的情況是為UserServiceImpl
創(chuàng)建了一個(gè)子類,并且所有方法都被覆蓋以應(yīng)用TransactionInterceptor
。但是,由于您的方法被標(biāo)記為final
,所以動(dòng)態(tài)創(chuàng)建的類不能覆蓋此方法。因此,該方法查看動(dòng)態(tài)創(chuàng)建的代理類中的字段實(shí)例,該實(shí)例始終為null
。
當(dāng)刪除final
方法時(shí),可以重寫該方法,應(yīng)用該行為,并且它將查看正確的字段實(shí)例(實(shí)際UserServiceImpl
而不是代理)。
禁用基于類的代理時(shí),您將獲得一個(gè)JDK動(dòng)態(tài)代理,它基本上是一個(gè)實(shí)現(xiàn)服務(wù)實(shí)現(xiàn)的所有接口的瘦包裝。它應(yīng)用添加的行為(事務(wù))并調(diào)用實(shí)際服務(wù)。不需要對(duì)實(shí)際類進(jìn)行擴(kuò)展,因此您可以代理最終方法(只要它是您的接口的一部分)。
這篇關(guān)于Spring Boot 2@Transaction批注使自動(dòng)連接的字段為空的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,