Spring Hibernate会话无明显原因关闭

Spring Hibernate会话无明显原因关闭,spring,hibernate,jpa,Spring,Hibernate,Jpa,我已经为此挣扎了好几天,我真的不知道这里发生了什么。 我有几个进程是由用户触发的,发生在一个单独的线程上,它执行一些操作,并更新数据库中的一个条目,用户可以检索它的进度。 直到最近,这一切都运行得很好,突然,有时,看起来与任何事情都不相关,这些进程在第一次尝试延迟加载实体时失败了。它们失败的原因是几个不同的错误中的一个,所有这些错误最终都源于hibernate Seision以某种方式关闭: org.hibernate.SessionException: Session is closed. T

我已经为此挣扎了好几天,我真的不知道这里发生了什么。 我有几个进程是由用户触发的,发生在一个单独的线程上,它执行一些操作,并更新数据库中的一个条目,用户可以检索它的进度。 直到最近,这一切都运行得很好,突然,有时,看起来与任何事情都不相关,这些进程在第一次尝试延迟加载实体时失败了。它们失败的原因是几个不同的错误中的一个,所有这些错误最终都源于hibernate Seision以某种方式关闭:

org.hibernate.SessionException: Session is closed. The read-only/modifiable setting is only accessible when the proxy is associated with an open session.
-

-

-

-

我正在使用spring@Transactional来管理我的事务

这是我的配置:

@Bean
public javax.sql.DataSource dataSource() {
    // update TTL so that the datasource will pick up DB failover - new IP
    java.security.Security.setProperty("networkaddress.cache.ttl", "30");
    HikariDataSource ds = new HikariDataSource();
    String jdbcUrl = "jdbc:mysql://" + plentyConfig.getHostname() + ":" + plentyConfig.getDbport() + "/"
            + plentyConfig.getDbname() + "?useSSL=false";
    ds.setJdbcUrl(jdbcUrl);
    ds.setUsername(plentyConfig.getUsername());
    ds.setPassword(plentyConfig.getPassword());
    ds.setConnectionTimeout(120000);
    ds.setMaximumPoolSize(20);
    return ds;
}

@Bean
public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
    JpaTransactionManager manager = new JpaTransactionManager();
    manager.setEntityManagerFactory(entityManagerFactory);
    return manager;
}

@Bean
@Autowired
public LocalContainerEntityManagerFactoryBean entityManagerFactory(javax.sql.DataSource dataSource) {
    LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
    factory.setDataSource(dataSource);
    factory.setPackagesToScan("com.rdthree.plenty.domain");
    Properties properties = new Properties();
    properties.put("org.hibernate.flushMode", "ALWAYS");
    properties.put("hibernate.cache.use_second_level_cache", "true");
    properties.put("hibernate.cache.use_query_cache", "true");
    properties.put("hibernate.cache.region.factory_class",
            "com.rdthree.plenty.config.PlentyInfinispanRegionFactory");
    properties.put("hibernate.cache.infinispan.statistics", "true");
    properties.put("hibernate.cache.infinispan.query", "distributed-query");
    properties.put("hibernate.enable_lazy_load_no_trans", "true");
    if (plentyConfig.getProfile().equals(PlentyConfig.UNIT_TEST)
            || plentyConfig.getProfile().equals(PlentyConfig.PRODUCTION_INIT)) {
        properties.put("hibernate.cache.infinispan.cfg", "infinispan-local.xml");
    } else {
        properties.put("hibernate.cache.infinispan.cfg", "infinispan.xml");
    }

    factory.setJpaProperties(properties);
    HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
    adapter.setShowSql(false);
    adapter.setDatabasePlatform("org.hibernate.dialect.MySQLDialect");
    factory.setJpaVendorAdapter(adapter);
    return factory;
}
它的工作方式是,用户触发的线程迭代计划集合并应用每个计划,应用计划的过程还更新数据库上的进度实体。 整个线程bean标记为事务性:

@Component
@Scope("prototype")
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.READ_COMMITTED)
public class TemplatePlanApplicationThreadBean extends AbstractPlentyThread implements TemplatePlanApplicationThread {

...

@Override
public void run() {
    startProcessing();
    try {
        logger.trace(
                "---Starting plan manifestation for " + fieldCropReplaceDatePlantationDates.size() + " fields---");
        List<Plan> plans = new ArrayList<>();
        for (FieldCropReplaceDatePlantationDates obj : fieldCropReplaceDatePlantationDates) {
            for (TemplatePlan templatePlan : obj.getTemplatePlans()) {
                try {
                    plans.add(planService.findActivePlanAndManifestTemplatePlan(templatePlan, organization,
                            obj.getPlantationDate(), obj.getReplacementStartDate(), obj.getFieldCrop(),
                            autoSchedule, schedulerRequestArguments, planApplicationProgress, false));
                } catch (ActivityException e) {
                    throw new IllegalArgumentException(e);
                }
            }
            Plan plan = plans.get(plans.size() - 1);
            plan = planService.getEntityById(plan.getId());
            if (plan != null) {
                planService.setUnscheduledPlanAsSelected(plan);
            }
            plans.clear();
        }
        if (planApplicationProgressService.getEntityById(planApplicationProgress.getId()) != null) {
            planApplicationProgressService.deleteEntity(planApplicationProgress.getId());
        }
    } catch (Exception e) {
        logger.error(PlentyUtils.extrapolateStackTrace(e));
        connector.createIssue("RdThreeLLC", "plenty-web",
                new GitHubIssueRequest("Template plan application failure",
                        "```\n" + PlentyUtils.extrapolateStackTrace(e) + "\n```", 1, new ArrayList<>(),
                        Lists.newArrayList("plentytickets")));
        planApplicationProgress.setFailed(true);
        planApplicationProgressService.saveEntity(planApplicationProgress);
    } finally {
        endProcessing();
    }
}
@组件
@范围(“原型”)
@事务性(传播=传播.REQUIRES\u NEW,隔离=隔离.READ\u COMMITTED)
公共类TemplatePlanApplicationReadBean扩展AbstractPlentyThread实现TemplatePlanApplicationRead{
...
@凌驾
公开募捐{
开始处理();
试一试{
logger.trace(
“---开始显示“+fieldCropReplaceDatePlantationDates.size()+”字段--”的计划;
列表计划=新建ArrayList();
对于(FieldCroPrePlaceDate种植日期对象:FieldCroPrePlaceDate种植日期){
对于(TemplatePlan TemplatePlan:obj.getTemplatePlans()){
试一试{
plans.add(planService.findactiveplan)和manifestTemplatePlan(templatePlan,organization,
obj.getPlantationDate(),obj.getReplacementStartDate(),obj.getFieldCrop(),
autoSchedule、SchedulerRequestStarGuments、planApplicationProgress、false);
}捕获(活动异常e){
抛出新的IllegalArgumentException(e);
}
}
计划=plans.get(plans.size()-1);
plan=planService.getEntityById(plan.getId());
如果(计划!=null){
planService.setUnscheduledPlanAsSelected(计划);
}
计划。清除();
}
if(planApplicationProgressService.getEntityById(planApplicationProgress.getId())!=null){
planApplicationProgressService.deleteEntity(planApplicationProgress.getId());
}
}捕获(例外e){
logger.error(PlentyUtils.extrapolateStackTrace(e));
connector.createIssue(“RdThreeLLC”,“plenty web”,
新建GitHubIssueRequest(“模板计划应用程序失败”,
“``\n”+PlentyUtils.extractionStatackTrace(e)+”\n```',1,新的ArrayList(),
列表。newArrayList(“plentytickets”);
planApplicationProgress.setFailed(true);
planApplicationProgressService.saveEntity(planApplicationProgress);
}最后{
endProcessing();
}
}
以下是线程调用的方法:

@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public synchronized Plan findActivePlanAndManifestTemplatePlan(TemplatePlan templatePlan,
        ServiceProviderOrganization organization, Date plantationDate, Date replacementDate, FieldCrop fieldCrop,
        boolean autoSchedule, SchedulerRequestArguments schedulerRequestArguments, Progress planProgress,
        boolean commit) throws ActivityException {
    Plan oldPlan = getLatestByFieldCrop(fieldCrop);
    List<Activity> activitiesToRemove = oldPlan != null
            ? findActivitiesToRemoveAfterDate(oldPlan, replacementDate != null ? replacementDate : new Date())
            : new ArrayList<>();
    List<PlanExpense> planExpensesToRemove = oldPlan != null
            ? findPlanExpensesToRemoveAfterDate(oldPlan, replacementDate != null ? replacementDate : new Date())
            : new ArrayList<>();
    Date oldPlanPlantationDate = oldPlan != null ? inferPlanDates(oldPlan).getPlantationDate() : null;
    if (oldPlan != null) {
        if (commit) {
            oldPlan.setReplaced(true);
        }
        buildPlanProfitProjectionForPlanAndField(oldPlan, Sets.newHashSet(activitiesToRemove),
                Sets.newHashSet(planExpensesToRemove));
    }
    if (commit) {
        for (Activity activity : activitiesToRemove) {
            activityService.deleteEntity(activity.getId());
        }
        for (PlanExpense planExpense : planExpensesToRemove) {
            planExpenseService.deleteEntity(planExpense.getId());
        }
    }
    oldPlan = oldPlan != null ? getEntityById(oldPlan.getId()) : null;
    Plan plan = manifestTemplatePlan(templatePlan, oldPlan, organization,
            plantationDate != null ? plantationDate : oldPlanPlantationDate, replacementDate, fieldCrop,
            autoSchedule, schedulerRequestArguments, planProgress, commit);
    if (!commit) {
        setPlanAllocationsUnscheduled(plan);
    }
    return plan;
}
@覆盖
@事务性(传播=传播。需要\u新建)
公共同步计划findActivePlanAndManifestTemplatePlan(TemplatePlan TemplatePlan,
服务提供商组织机构,种植日期,更换日期,田间作物,
布尔值自动调度,调度请求启动项调度请求启动项,进度计划进度,
布尔提交)抛出ActivityException{
Plan oldPlan=getLatestByFieldCrop(fieldCrop);
列出活动删除=旧计划!=空
?findActivitiesToRemoveAfterDate(旧计划,replacementDate!=null?replacementDate:新日期())
:new ArrayList();
List planExpensesToRemove=oldPlan!=null
?findPlanExpensesToRemoveAfterDate(旧计划,替换日期!=null?替换日期:新日期())
:new ArrayList();
日期OldPlantPlantationDate=oldPlan!=null?推断计划日期(oldPlan)。getPlantationDate():null;
if(oldPlan!=null){
如果(提交){
oldPlan.setReplaced(真);
}
buildPlanProfitProjectionForPlanAndField(旧计划,集合。新哈希集合(活动存储移动),
Sets.newHashSet(planExpensesToRemove));
}
如果(提交){
对于(活动活动:活动存储移动){
activityService.deleteEntity(activity.getId());
}
用于(PlaneExpense PlaneExpense:PlaneExpenseStoreMove){
planExpenseService.deleteEntity(planExpense.getId());
}
}
oldPlan=oldPlan!=null?getEntityById(oldPlan.getId()):null;
计划计划=清单模板计划(模板计划、旧计划、组织、,
种植园日期!=null?种植园日期:旧计划种植园日期,替换日期,田间作物,
自动调度、调度请求、计划进度、提交);
如果(!提交){
setPlanAllocationsUnscheduled(计划);
}
退货计划;
}
最要命的是错误只是偶尔发生,所以我无法真正调试它,也无法将它与任何东西关联起来

关于什么会导致会议结束,你有什么想法吗

我试着关闭其他线程,所以基本上这是唯一一个正在运行的线程,没有帮助


谢谢

交易在哪里定义?在新线程上?请参阅更新的帖子,谢谢
java.lang.NullPointerException
 at com.mysql.jdbc.ResultSetImpl.checkColumnBounds(ResultSetImpl.java:766)
@Bean
public javax.sql.DataSource dataSource() {
    // update TTL so that the datasource will pick up DB failover - new IP
    java.security.Security.setProperty("networkaddress.cache.ttl", "30");
    HikariDataSource ds = new HikariDataSource();
    String jdbcUrl = "jdbc:mysql://" + plentyConfig.getHostname() + ":" + plentyConfig.getDbport() + "/"
            + plentyConfig.getDbname() + "?useSSL=false";
    ds.setJdbcUrl(jdbcUrl);
    ds.setUsername(plentyConfig.getUsername());
    ds.setPassword(plentyConfig.getPassword());
    ds.setConnectionTimeout(120000);
    ds.setMaximumPoolSize(20);
    return ds;
}

@Bean
public JpaTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
    JpaTransactionManager manager = new JpaTransactionManager();
    manager.setEntityManagerFactory(entityManagerFactory);
    return manager;
}

@Bean
@Autowired
public LocalContainerEntityManagerFactoryBean entityManagerFactory(javax.sql.DataSource dataSource) {
    LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
    factory.setDataSource(dataSource);
    factory.setPackagesToScan("com.rdthree.plenty.domain");
    Properties properties = new Properties();
    properties.put("org.hibernate.flushMode", "ALWAYS");
    properties.put("hibernate.cache.use_second_level_cache", "true");
    properties.put("hibernate.cache.use_query_cache", "true");
    properties.put("hibernate.cache.region.factory_class",
            "com.rdthree.plenty.config.PlentyInfinispanRegionFactory");
    properties.put("hibernate.cache.infinispan.statistics", "true");
    properties.put("hibernate.cache.infinispan.query", "distributed-query");
    properties.put("hibernate.enable_lazy_load_no_trans", "true");
    if (plentyConfig.getProfile().equals(PlentyConfig.UNIT_TEST)
            || plentyConfig.getProfile().equals(PlentyConfig.PRODUCTION_INIT)) {
        properties.put("hibernate.cache.infinispan.cfg", "infinispan-local.xml");
    } else {
        properties.put("hibernate.cache.infinispan.cfg", "infinispan.xml");
    }

    factory.setJpaProperties(properties);
    HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
    adapter.setShowSql(false);
    adapter.setDatabasePlatform("org.hibernate.dialect.MySQLDialect");
    factory.setJpaVendorAdapter(adapter);
    return factory;
}
@Component
@Scope("prototype")
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.READ_COMMITTED)
public class TemplatePlanApplicationThreadBean extends AbstractPlentyThread implements TemplatePlanApplicationThread {

...

@Override
public void run() {
    startProcessing();
    try {
        logger.trace(
                "---Starting plan manifestation for " + fieldCropReplaceDatePlantationDates.size() + " fields---");
        List<Plan> plans = new ArrayList<>();
        for (FieldCropReplaceDatePlantationDates obj : fieldCropReplaceDatePlantationDates) {
            for (TemplatePlan templatePlan : obj.getTemplatePlans()) {
                try {
                    plans.add(planService.findActivePlanAndManifestTemplatePlan(templatePlan, organization,
                            obj.getPlantationDate(), obj.getReplacementStartDate(), obj.getFieldCrop(),
                            autoSchedule, schedulerRequestArguments, planApplicationProgress, false));
                } catch (ActivityException e) {
                    throw new IllegalArgumentException(e);
                }
            }
            Plan plan = plans.get(plans.size() - 1);
            plan = planService.getEntityById(plan.getId());
            if (plan != null) {
                planService.setUnscheduledPlanAsSelected(plan);
            }
            plans.clear();
        }
        if (planApplicationProgressService.getEntityById(planApplicationProgress.getId()) != null) {
            planApplicationProgressService.deleteEntity(planApplicationProgress.getId());
        }
    } catch (Exception e) {
        logger.error(PlentyUtils.extrapolateStackTrace(e));
        connector.createIssue("RdThreeLLC", "plenty-web",
                new GitHubIssueRequest("Template plan application failure",
                        "```\n" + PlentyUtils.extrapolateStackTrace(e) + "\n```", 1, new ArrayList<>(),
                        Lists.newArrayList("plentytickets")));
        planApplicationProgress.setFailed(true);
        planApplicationProgressService.saveEntity(planApplicationProgress);
    } finally {
        endProcessing();
    }
}
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public synchronized Plan findActivePlanAndManifestTemplatePlan(TemplatePlan templatePlan,
        ServiceProviderOrganization organization, Date plantationDate, Date replacementDate, FieldCrop fieldCrop,
        boolean autoSchedule, SchedulerRequestArguments schedulerRequestArguments, Progress planProgress,
        boolean commit) throws ActivityException {
    Plan oldPlan = getLatestByFieldCrop(fieldCrop);
    List<Activity> activitiesToRemove = oldPlan != null
            ? findActivitiesToRemoveAfterDate(oldPlan, replacementDate != null ? replacementDate : new Date())
            : new ArrayList<>();
    List<PlanExpense> planExpensesToRemove = oldPlan != null
            ? findPlanExpensesToRemoveAfterDate(oldPlan, replacementDate != null ? replacementDate : new Date())
            : new ArrayList<>();
    Date oldPlanPlantationDate = oldPlan != null ? inferPlanDates(oldPlan).getPlantationDate() : null;
    if (oldPlan != null) {
        if (commit) {
            oldPlan.setReplaced(true);
        }
        buildPlanProfitProjectionForPlanAndField(oldPlan, Sets.newHashSet(activitiesToRemove),
                Sets.newHashSet(planExpensesToRemove));
    }
    if (commit) {
        for (Activity activity : activitiesToRemove) {
            activityService.deleteEntity(activity.getId());
        }
        for (PlanExpense planExpense : planExpensesToRemove) {
            planExpenseService.deleteEntity(planExpense.getId());
        }
    }
    oldPlan = oldPlan != null ? getEntityById(oldPlan.getId()) : null;
    Plan plan = manifestTemplatePlan(templatePlan, oldPlan, organization,
            plantationDate != null ? plantationDate : oldPlanPlantationDate, replacementDate, fieldCrop,
            autoSchedule, schedulerRequestArguments, planProgress, commit);
    if (!commit) {
        setPlanAllocationsUnscheduled(plan);
    }
    return plan;
}