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