春季启动。尝试打印非存储实体时没有代理

时间:2019-04-16 11:23:36

标签: java spring hibernate spring-boot jpa

从常规的Spring Boot项目中,我有一个实体:

@Entity
public class Job {
  @Id
  @GeneratedValue
  private long id;

  @ManyToOne(fetch = EAGER)
  @JoinColumn
  private Config config;

  ...
}

toString()通常是由Eclipse组成的,可以对字段进行常规打印。 当我尝试对工作流程进行基本模拟并执行以下操作时:

@Service
public class TestService {
   private static final Logger logger = LoggerFactory.getLogger("test");

   @Transactional
   public void addJob(Job job) {
      logger.info("Adding job {}", job);
   }
   ...
}

@Service
public class Tests {
   @Autowired
   private TestService service;

   @Autowired
   private ConfigDao configDao;

   @EventListener(ApplicationReadyEvent.class)
   public void testJobAdd() {
      Job job = new Job();
      job.setConfig(configDao.findAll().get(0));
      service.addJob(job);
   }
}

这为Job实体的@ManyToOne元素提供了“无会话”例外。

我确实知道这与完成工作的通常方式相去甚远,但是我仍然想知道为什么会发生这种异常。 Pojo创建时将交付“ Config”,因此甚至不应进行“获取”。

我可以先存储对象,然后再提供一个完全缓存的实体,该实体可以工作,但是我想在对象到达JPA之前记录作业的详细信息。

堆栈:

019-04-16 15:07:52 ERROR [localhost-startStop-1] SpringApplication.reportFailure: Application run failed
org.hibernate.LazyInitializationException: could not initialize proxy [org.applebase.AutomationAgent.entity.sessionConfig.SessionConfig#1403] - no Session
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:169)
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:309)
    at org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor.intercept(ByteBuddyInterceptor.java:45)
    at org.hibernate.proxy.ProxyConfiguration$InterceptorDispatcher.intercept(ProxyConfiguration.java:95)
    at org.applebase.AutomationAgent.entity.sessionConfig.SessionConfig$HibernateProxy$GOSm9GNJ.getName(Unknown Source)
    at org.applebase.AutomationAgent.service.impl.JobServiceImpl.save(JobServiceImpl.java:28)
    at org.applebase.AutomationAgent.service.impl.JobServiceImpl$$FastClassBySpringCGLIB$$13b2fdc0.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:749)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
    at org.applebase.AutomationAgent.service.impl.JobServiceImpl$$EnhancerBySpringCGLIB$$ae28e0fc.save(<generated>)
    at org.applebase.AutomationAgent.service.impl.SomeTestService.formingAJob(SomeTestService.java:58)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:564)
    at org.springframework.context.event.ApplicationListenerMethodAdapter.doInvoke(ApplicationListenerMethodAdapter.java:261)
    at org.springframework.context.event.ApplicationListenerMethodAdapter.processEvent(ApplicationListenerMethodAdapter.java:179)
    at org.springframework.context.event.ApplicationListenerMethodAdapter.onApplicationEvent(ApplicationListenerMethodAdapter.java:142)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:402)
    at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:359)
    at org.springframework.boot.context.event.EventPublishingRunListener.running(EventPublishingRunListener.java:105)
    at org.springframework.boot.SpringApplicationRunListeners.running(SpringApplicationRunListeners.java:78)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:332)
    at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.run(SpringBootServletInitializer.java:157)
    at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:137)
    at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:91)
    at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:171)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5245)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1420)
    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1410)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
    at java.base/java.lang.Thread.run(Thread.java:844)

1 个答案:

答案 0 :(得分:1)

您评论说,您的@XToMany实体中存在Job个关系。由于所有一对多均为Lazy,因此导致LazyInitializationException。这些字段无法在事务中实例化,因为它已传递给用@Transactional注释的方法(它是在事务范围之外初始化的)。您必须将configDao.findAll().get(0)移至事务方法作为解决方法:

@Service
public class TestService {

   @Autowired
   private ConfigDao configDao;

   private static final Logger logger = LoggerFactory.getLogger("test");

   @Transactional
   public void addJob() {
      Job job = configDao.findAll().get(0);
      logger.info("Adding job {}", job);
   }
   ...
}

@Service
public class Tests {
   @Autowired
   private TestService service;

   @EventListener(ApplicationReadyEvent.class)
   public void testJobAdd() {
      Job job = new Job();
      job.setConfig();
      service.addJob(job);
   }
}