首页 文章

org.hibernate.LazyInitializationException:无法初始化代理 - 没有用于hibernate JPA的会话

提问于
浏览
-1

我想在tomcat容器启动之前通过hibernate会话从tomcat监听器查询数据库 . 这里我得到了org.hibernate.LazyInitializationException:无法初始化代理 - 没有会话错误 . 此外,当尝试使用hibernate会话附加对象时,它会给出错误

我的设置:1 . 有一个tomcat监听器,其中同样实现ServletContextListener 2.通过这个监听器启动spring applicationcontext 3.在spring中配置hibernate和JPA

listener:在这个监听器中,我正在尝试加载我的spring applicationContext并通过hibernate会话调用我的DAO来获取DB数据 . 另外我开始一个线程池来分配任务取决于数据库查询

@Override
    public void contextInitialized(ServletContextEvent sce) {

    ServletContext servletContext = sce.getServletContext();

        logger.debug("initializing the servletContextListener for AlarmThreadPool...");

        try {

            String springFileName = sce.getServletContext().getInitParameter("CONFIG_SPRING_FILE");
            ApplicationContextContainer.getInstance(springFileName, sce.getServletContext());

            IAriCloudDAO ariCloudDAO = (IAriCloudDAO) ApplicationContextContainer.getBean("ariCloudDAO");
            logger.debug("got the dao bean...");
            if (null != ariCloudDAO) {
                System.out.println("got the instace of DAO");
                int metricID = 1;
                List<CloudAlarmConfig> cloudAlarmConfigs = ariCloudDAO.getAllUsageAlarm(metricID);
                logger.info("the DAO entry got as " +cloudAlarmConfigs);
            }

            ThreadFactory threadFactory = new ThreadFactoryBuilder()
                    .setNameFormat("alarm-thread-%d")
                    //.setDaemon(true)
                    .build();

            ScheduledExecutorService exec = Executors.newScheduledThreadPool(2, threadFactory);
            servletContext.setAttribute("alarmThreadPool", exec);

        }catch (Exception e) {
            logger.fatal("ERROR::", e);
        }                   
    }

DAO IMPL:

@Override
@Transactional
@SuppressWarnings("unchecked")
public List<CloudAlarmConfig> getAllUsageAlarm(int metricID) {

    Session session = mySessionFactory.getCurrentSession();

    Query q = session
            .createQuery("SELECT e FROM CloudAlarmConfig e WHERE METRIC=:METRIC");
    q.setParameter("METRIC", metricID);
    logger.debug("query string got as :"+ q.getQueryString());
    List<CloudAlarmConfig> cloudAlarmConfigs = q.list();

    if (!cloudAlarmConfigs.isEmpty()) {
        return cloudAlarmConfigs;
    } else {
        return new ArrayList<CloudAlarmConfig>();
    }
}

JPA实体:

我正在使用LazyInitialization进行实体加入 .

@JsonIgnore
    @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "USER_ID", referencedColumnName = "ID")
    private UserEntity userEntity;

尝试执行DAO调用时获取以下异常 .

org.hibernate.LazyInitializationException:无法在org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:285)的org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:164)初始化代理 - 没有会话.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185)位于java.lang.String.valueOf的com.aricent.aricloud.entity.UserEntity _ $$ _ javassist_6.toString(UserEntity _ $$ _ javassist_6.java) (String.java:2902)在java.lang.StringBuilder.append(StringBuilder.java:128)在com.aricent.aricloud.entity.CloudAlarmConfig.toString(CloudAlarmConfig.java:234)在java.lang.String.valueOf( String.java:2902)at java.lang.StringBuilder.append(StringBuilder.java:128)

正如我在几篇文章中所理解的那样,hibernate会话仅针对一个请求生效,然后关闭,实体已从会话中分离出来 . 但是当试图用DAO impl中的下面的代码重新连接它时,它给了我不同的错误

Session session = mySessionFactory.getCurrentSession();
session.update(CloudAlarmConfig.class);

org.hibernate.MappingException:未知实体:在org.hibernate.internal.SessionImpl.getEntityPersister(SessionImpl.java:1433)在org.hibernate.internal.SessionFactoryImpl.getEntityPersister(SessionFactoryImpl.java:1141)java.lang.Class中在在org.hibernate.event.internal.DefaultUpdateEventListener.performSaveOrUpdate(DefaultUpdateEventListener.java:55)在org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:233) DefaultSaveOrUpdateEventListener.java:90)在org.hibernate.internal.SessionImpl.fireUpdate(SessionImpl.java:786)在org.hibernate.internal.SessionImpl.update(SessionImpl.java:778)在org.hibernate.internal.SessionImpl.update (SessionImpl.java:774)at com.aricent.aricloud.dao.AricloudDAOImpl.getAllUsageAlarm(AricloudDAOImpl.java:959)

我怎么能克服这一点 . 请建议 .

1 回答

  • 1

    您正在覆盖 CloudAlarmConfig 类的 toString() 方法并尝试访问延迟加载的 UserEntity 实例 .

    所以在你的代码中 -

    List<CloudAlarmConfig> cloudAlarmConfigs = ariCloudDAO.getAllUsageAlarm(metricID);
    logger.info("the DAO entry got as " +cloudAlarmConfigs);
    

    这使得调用toString方法在内部尝试访问"UserEntity",因此当您尝试访问Hibernate会话之外的实体时,您将获得Lazy异常 org.hibernate.LazyInitializationException: could not initialize proxy - no Session at .

    要解决此问题,您必须在会话仍处于打开状态时加载 UserEntity 的实例 .

    Jens在他的评论中提到了第二个例外,即 org.hibernate.MappingException: Unknown entity: java.lang.Class at . 代码应该是这样的:

    Session session = mySessionFactory.getCurrentSession();
    session.update(cloudAlarmConfig);
    

    这里 cloudAlarmConfig 表示 CloudAlarmConfig class 的实例 .

    Update:

    要更新记录,首先应该有一个具有正确id的有效对象 . 所以你可以尝试这样:

    Session session = mySessionFactory.getCurrentSession();
     CloudAlarmConfig cloudAlarmConfig = (CloudAlarmConfig) session.get(CloudAlarmConfig.class,100); // Assuming 100 is one of the primary key in Databse table for CloudAlarmConfig entity.     
    
    // Do some modifications to this object, then call the update operation.
    session.update(cloudAlarmConfig);
    

相关问题