我有一个如下的事件处理程序类:
@Component
@RepositoryEventHandler(DonationOffer.class)
public class DonationOfferEventHandler {
@Autowired
DonationOfferNotificationService notificationService;
@HandleAfterSave
public void handleAfterSave(DonationOffer donationOffer){
Integer donationOfferId = donationOffer.getDonationOfferId();
System.out.println("updating donation offer");
switch (donationOffer.getOfferStatus()){
case Accepted:
notificationService.generateAcceptedNotification(donationOfferId);
break;
case Rejected:
notificationService.generateRejectedNotification(donationOfferId);
break;
case Cancelled:
notificationService.generateCancelledNotification(donationOfferId);
break;
}
}
}
春季回购如下:
@Transactional
public interface DonationOfferRepo extends PagingAndSortingRepository<DonationOffer,Integer>{
@Modifying
@Query(
"update DonationOffer d " +
"set offerStatus = :offerStatus " +
"where d.donationOfferId = :donationOfferId"
)
@RestResource(path="updateStatus")
int updateStatus(
@Param("donationOfferId") Integer donationOfferId,
@Param("offerStatus") OfferStatus offerStatus
);
}
问题处理程序是在PUT请求的情况下被调用的,原因是当我调用updateStatus()时,即未调用@HandleAfterSave方法,
a get request to /api/donationOffers/search/updateStatus?donationOfferId=45&offerStatus=Cancelled
如果我缺少某些东西,可以帮忙吗?或者它是默认行为,即仅通过PUT请求才调用@HandleAfterSave吗?
更新: 我创建了一种使用repo save方法测试事件处理程序的方法,如下所示。在这种情况下也不会调用事件处理程序。
@GetMapping(value="/savetest")
@Transactional
public ResponseEntity saveTesT(){
DonationOffer donationOffer = donationOfferRepo.findOne(1);
donationOffer.setOfferedBottles(donationOffer.getOfferedBottles()+1);
donationOfferRepo.save(donationOffer);
return new ResponseEntity(new StringWrapper("OK"), HttpStatus.OK);
}
答案 0 :(得分:2)
为了从HandleBeforeSave触发事件,您需要执行PUT请求。如果您正在执行POST请求,则正确的事件处理程序将为HandleBeforeCreate。
UPDATE:我猜测监听器方法没有被调用,原因与查询不调用JPA prePersist,postPersist,preUpdate ...等事件的原因相同。查询对EntityManager.persis更新有不同的执行途径。实体管理器基于身份进行工作,因此可以保证实体实际上已被更新。使用查询时无法得知相同的内容。通常,实体管理器将执行一个查询以获取实体,然后对其进行分析以进行更改,然后将进行UPDATE,或者在不进行更改的情况下将不进行UPDATE。没有机制可以确定执行查询时是否确实发生了更新。
根据文档@Modifying注释,不能保证实际上会进行修改。它保证在调用方法后将清除该会话。这背后的原因再次是查询的执行路径与普通的persist,merge方法不同,并且您不能保证会话将保持完整性。因此,@ Modifying将确保已清除它。