@Override public List<CgSubject> queryByYearId(Integer yearId) { Specification<CgSubject> specification = (root, query, cb) -> { List<Predicate> predicates = new ArrayList<>(); // 所有的断言 predicates.add(cb.equal(root.get("deleted"), 0)); predicates.add(cb.equal(root.get("yearId"), yearId)); predicates.add(cb.equal(root.get("status"), 1)); return cb.and(predicates.toArray(new Predicate[0])); }; List<CgSubject> cgSubjectList = cgSubjectMapper.findAll(specification); cgSubjectList.forEach(temp -> temp.setTempName((temp.getType() == 1 ? "线上-" : "线下-") + temp.getName())); return cgSubjectList; }
另外还有一段存储的代码
@Transactional public List<CgOrder> importGroupBuyOrderExcel(List<Map<String, Object>> rowList, User creator) { List<CgOrder> cgOrderList = transform(rowList); Integer state = cgOrderList.get(0).getState(); for (CgOrder o : cgOrderList) { if (!state.equals(o.getState())) { throw new BusinessException(null, "所有订单的支付状态不统一"); } CgProduct p = o.getCgProduct(); cgProductRepository.save(p); o.setProductId(p.getId()); o.setCreateName(creator.getUserName()); cgOrderRepository.save(o); o.setOrderNo(AbstractTeacherTrainOrderService.getOrderNo(o.getId())); cgOrderRepository.save(o); } return cgOrderList; }
当然,第二段代码存储是有点问题,但不影响这个要说的这个问题,第一段代码我们通过spring jpa托管器获取到了cgSubject的列表,并对其名称进行更新,然后第二段代码中会在transform()方法中调用第一段代码,然后下面用spring jpa 进行save操作。这个时候会发现cgSubject也会被更新,原因就是用到了spring jpa托管器,在第一段代码更新name的时候相当于就会数据库的update操作,然后通过后面的save操作触发。
解决办法:
1.可以通过cgSubject实体类增加冗余字段,然后用@Transient 标注。
2.可以不使用spring jpa托管器,通过本地sql来查询cgSubject列表(未尝试,但感觉可行)。
这算是刚用spring jpa 碰到的一个坑吧,用了两个小时才发现并解决问题。