提问帖
为什么不加@Transactional注解就会报错
在程序不添加@Transactional就会报出could not initialize proxy - no Session这样的错误,百度之后解决方法部分网友给出的解决方法是在多对多或多对一中关闭lazy load
但是这与我不写@Transactional毫无关联,希望能被解释一下
错误内容
java.lang.IllegalStateException: Failed to execute ApplicationRunner
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:807) ~[spring-boot-2.1.2.RELEASE.jar:2.1.2.RELEASE]
at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:794) ~[spring-boot-2.1.2.RELEASE.jar:2.1.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:324) ~[spring-boot-2.1.2.RELEASE.jar:2.1.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260) ~[spring-boot-2.1.2.RELEASE.jar:2.1.2.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248) ~[spring-boot-2.1.2.RELEASE.jar:2.1.2.RELEASE]
at geektime.spring.data.datasourcedemo.JpaDemoApplication.main(JpaDemoApplication.java:34) ~[classes/:na]
Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: geektime.spring.data.datasourcedemo.CoffeeOrder.items, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:597) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:216) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:576) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:147) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.collection.internal.PersistentBag.iterator(PersistentBag.java:303) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at java.base/java.lang.Iterable.forEach(Iterable.java:74) ~[na:na]
at geektime.spring.data.datasourcedemo.JpaDemoApplication.lambda$findOrders$2(JpaDemoApplication.java:73) ~[classes/:na]
at java.base/java.util.ArrayList.forEach(ArrayList.java:1540) ~[na:na]
at geektime.spring.data.datasourcedemo.JpaDemoApplication.findOrders(JpaDemoApplication.java:71) ~[classes/:na]
at geektime.spring.data.datasourcedemo.JpaDemoApplication.run(JpaDemoApplication.java:41) ~[classes/:na]
at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:804) ~[spring-boot-2.1.2.RELEASE.jar:2.1.2.RELEASE]
@SpringBootApplication
@Slf4j
@EnableJpaRepositories
@EnableTransactionManagement
public class JpaDemoApplication implements ApplicationRunner {
@Autowired
private CoffeeRepository coffeeRepository;
@Autowired
private CoffeeOrderRepository orderRepository;
public static void main(String[] args) {
SpringApplication.run(JpaDemoApplication.class, args);
}
//@Transactional
@Override
public void run(ApplicationArguments args) throws Exception {
initOrders();
findOrders();
}
private void initOrders() {
Coffee espresso = Coffee.builder().name("espresso").price(Money.of(CurrencyUnit.of("CNY"), 20.0)).build();
coffeeRepository.save(espresso);
log.info("Coffee: {}", espresso);
Coffee latte = Coffee.builder().name("latte").price(Money.of(CurrencyUnit.of("CNY"), 30.0)).build();
coffeeRepository.save(latte);
log.info("Coffee: {}", latte);
CoffeeOrder order = CoffeeOrder.builder().customer("Li Lei").items(Collections.singletonList(espresso)).state(OrderState.INIT).build();
orderRepository.save(order);
log.info("Order: {}", order);
order = CoffeeOrder.builder().customer("Li Lei").items(Arrays.asList(espresso, latte)).state(OrderState.INIT).build();
orderRepository.save(order);
log.info("Order: {}", order);
}
private void findOrders() {
coffeeRepository.findAll(Sort.by(Sort.Direction.DESC, "id")).forEach(c -> log.info("Loading {}", c));
List<CoffeeOrder> list = orderRepository.findTop3ByOrderByUpdateTimeDescIdAsc();
log.info("findTop3ByOrderByUpdateTimeDescIdAsc: {}", getJoinedOrderId(list));
list = orderRepository.findByCustomerOrderById("Li Lei");
log.info("findByCustomerOrderById: {}", getJoinedOrderId(list));
list.forEach(o -> {
log.info("Order {}", o.getId());
o.getItems().forEach(i -> log.info("Item {}", i));
});
list = orderRepository.findByItems_Name("latte");
log.info("findByItems_Name: {}", getJoinedOrderId(list));
}
private String getJoinedOrderId(List<CoffeeOrder> list) {
return list.stream().map(o -> o.getId().toString()).collect(Collectors.joining(","));
}
}