尝试在以@Transactional注释的Spring @Service类中的同一方法内检索子实体时出现LazyInitializationException

时间:2019-05-17 08:42:20

标签: hibernate spring-boot jpa spring-data-jpa

我在spring-boot项目的服务类中得到org.hibernate.LazyInitializationException。尽管我已经看到许多有关此异常的问题,但找不到与我的情况类似的东西。

我正在尝试将一个子实体的集合加载到@Transactional带注释的服务方法中,如下所示。

@Override
public Order addOrderPayment(OrderPaymentRQ form, Integer orderId) {
    Order order = repository.findById(orderId).orElseThrow(EntityNotFoundException::new);
    OrderPayment orderPayment = new OrderPayment();
    BeanUtils.copyProperties(form, orderPayment);
    order.getOrderPayments().add(orderPayment); //Exception thrown at this line
    repository.save(order);
    return order;
}

特定的异常抛出在order.getOrderPayments()上。

当我尝试执行以下集成测试时会发生这种情况。

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class OrdersRestControllerTest {

final Integer EDIT_ID = 2;

@Autowired
MockMvc mockMvc;

@Autowired
ObjectMapper mapper;

@Autowired
CarsService carsService;

@Autowired
OrdersService ordersService;

@Test
public void removeOrderPayment() throws Exception {
    OrderPaymentRQ payment = new OrderPaymentRQ();
    payment.setDescription("advance payment");
    BigDecimal amount = BigDecimal.valueOf(2000.50);
    payment.setAmount(amount);
    payment.setPaymentMethod(PaymentMethod.CASH);
    payment.setDate(LocalDate.now());

    Order order = ordersService.findById(EDIT_ID).get();
    ordersService.addOrderPayment(payment, EDIT_ID); //This line causes the exception
    OrderPayment toDelete = ordersService.getOrderPayments(EDIT_ID).get(0);

    MvcResult mvcResult = mockMvc.perform(delete("/orders/" + EDIT_ID + "/orderPayments/" + toDelete.getId()).contentType(MediaType.APPLICATION_JSON))
            .andExpect(status().isCreated())
            .andExpect(jsonPath("$.id", is(EDIT_ID)))
            .andReturn();

    Order orderReturned = mapper.readValue(mvcResult.getResponse().getContentAsString(), Order.class);
    assertEquals(order.getPayments().subtract(toDelete.getAmount()), orderReturned.getPayments());

}
}

实体关系如下(单向OneToMany)。

@Data
@Entity
public class Order implements Serializable{
     @Getter
     @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
     @JoinColumn(name = "order_id", nullable = false)
     @OrderBy("date DESC")
     List<OrderPayment> orderPayments = new ArrayList<>();

     other properties...
}

@Data
@Entity
public class OrderPayment implements Serializable{
    properties...
}

我的理解是,不应在引发异常的行处关闭事务,因为它位于同一@Transactional方法内。

当我用@Transactional注释测试类时,不会引发异常。这样做不会将数据持久保存到数据库中,所以我不能保证生产时的正确行为。

能否请您帮我弄清楚我在做什么错。

编辑:添加了存储库

public interface OrdersRepository extends CustomRepository<Order, Integer> {
}

@NoRepositoryBean
public interface CustomRepository<T, ID extends Serializable> extends PagingAndSortingRepository<T, ID>, QuerydslPredicateExecutor<T> {

}

0 个答案:

没有答案