首页 > 解决方案 > Spring:EntityManager 和 Spring Repository 是否不在同一上下文中工作?

问题描述

我有两个实体:

class Checkbook{
   ...
   private int canceledChecks;
   ...
}

class Check{
   ...
   @ManyToOne
   private Checkbook checkbook;

   private int status;
   ...
}

我想在取消a 时增加实体canceledChecks中的数量,所以我为此创建了一个事件侦听器,如下所示:CheckbookCheck(status become 1)

@Component
public class CheckChangeListener implements PreUpdateEventListener {

    @PersistenceContext
    private EntityManager em;

    @Override
    public boolean onPreUpdate(PreUpdateEvent event) {

        if(event.getEntity() instanceof Check){
            Check check = (Check)event.getEntity();
            CheckBook checkbook = check.getCheckBook();
            int oldStatus = getStatusFromEntityState(event.getOldState(), event);
            int newStatus = getStatusFromEntityState(event.getState(), event);

            if(oldStatus != newStatus && newStatus = 1){//means check is updated and canceled
                 checkbook.setCanceledChecks(checkbook.getCanceledChecks() + 1);
                 em.persist(checkbook); // persist new checkbook changes
            }
        }

        return false;
    }

    private int getStatusFromEntityState(Object[] state, PreUpdateEvent event){
        String[] properties = event.getPersister().getEntityMetamodel().getPropertyNames();
        int pos = -1;
        for (int i = 0; i < properties.length; i++) {
            if(properties[i].equals("status")) pos = i;
        }

        return (Integer)state[pos];
    }

现在在CheckController

@RestController
@RequestMapping("/api/check")
public class CheckController {

    @Autowired
    private CheckRepository repository;

    @PutMapping("/{id}/cancel")
    public ResponseEntity<Check> cancel(@PathVariable Long id) throws NotFoundException {
        Check check = repository.findById(id)
                .orElseThrow(() -> new NotFoundException("Check with id "+id+" not found!"));

        check.setStatus(1);

        repository.save(check);

        return ResponseEntity.status(HttpStatus.ACCEPTED).body(check);
    }
}

现在奇怪的是,正在调用侦听器,但支票簿没有更新。
但是,当我像这样更改控制器时:

@RestController
@RequestMapping("/api/check")
public class CheckController {

    @Autowired
    private CheckRepository repository;

    @PersistenceContext
    private EntityManager em;

    @Transactional
    @PutMapping("/{id}/cancel")
    public ResponseEntity<Check> cancel(@PathVariable Long id) throws NotFoundException {
        Check check = repository.findById(id)
                .orElseThrow(() -> new NotFoundException("Check with id "+id+" not found!"));

        check.setStatus(1);

        em.persist(check);
        em.flush();

        return ResponseEntity.status(HttpStatus.ACCEPTED).body(check);
    }
}

现在它可以工作了,并且Check正在与Checkbook!! 我认为这Spring data JPA在与 相同的事务中有效EntityManager,对吗?
我来自一个Symfony背景,我们只有EntityManager第二个场景对我来说更有意义(尽管我必须添加@Transactional注释才能使其工作)

为什么第二个场景有效而第一个无效?!

标签: javaspringspring-data-jpahibernate-entitymanager

解决方案


推荐阅读