Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/reporting-services/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Hibernate在CICS上的应用程序启动时连接到DB2_Java_Db2_Websphere Liberty_Cics_Db2 Zos - Fatal编程技术网

Java Hibernate在CICS上的应用程序启动时连接到DB2

Java Hibernate在CICS上的应用程序启动时连接到DB2,java,db2,websphere-liberty,cics,db2-zos,Java,Db2,Websphere Liberty,Cics,Db2 Zos,我们正在WebSphereLiberty上运行一个简单的webapp,它使用Hibernate作为持久性提供者(作为库包含在WAR文件中) 当应用程序启动时,Hibernate被初始化,它将打开到DB2的连接并发出一些SQL语句。但是,在CICS上运行并使用JDBCType2驱动程序数据源时,这会失败。将记录以下消息(为了可读性,需要额外换行): WARN org.hibernate.engine.jdbc.env.internal.jdbc环境启动器- HH000342:无法获取到查询元数据的

我们正在WebSphereLiberty上运行一个简单的webapp,它使用Hibernate作为持久性提供者(作为库包含在WAR文件中)

当应用程序启动时,Hibernate被初始化,它将打开到DB2的连接并发出一些SQL语句。但是,在CICS上运行并使用JDBCType2驱动程序数据源时,这会失败。将记录以下消息(为了可读性,需要额外换行):

WARN org.hibernate.engine.jdbc.env.internal.jdbc环境启动器-
HH000342:无法获取到查询元数据的连接:[jcc][50053][12310][4.19.56]
T2zOS异常:[jcc][T2zOS]T2ZOSICSAPI.checkApiStatus:
线程与CICS-DB2不兼容:CICS\u区域\u但\u API\u不允许的错误代码=-4228,SQLSTATE=null
...
错误org.hibernate.hql.spi.id.IdTableHelper-无法获取JDBC连接
com.ibm.db2.jcc.am.SqlException:[jcc][50053][12310][4.19.56]T2zOS异常:[jcc][T2zOS]T2zosCicsApi.checkApiStatus:
线程与CICS-DB2不兼容:CICS\u区域\u但\u API\u不允许的错误代码=-4228,SQLSTATE=null
在com.ibm.db2.jcc.am.kd.a(未知源)~[db2jcc4.jar:?]
...
在com.ibm.db2.jcc.t2zos.T2zosConnection.a(未知源)~[db2jcc4.jar:?]
...
在com.ibm.db2.jcc.DB2SimpleDataSource.getConnection(未知源)~[db2jcc4.jar:?]
在com.ibm.cics.wlp.jdbc.internal.CICSDataSource.getConnection(CICSDataSource.java:176)~[?:?]
在org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122)~[our app.war:5.1.0.Final]
在org.hibernate.internal.SessionFactoryImpl$3.获得连接(sessionfactorympl.java:643)~[our app.war:5.1.0.Final]
在org.hibernate.hql.spi.id.IdTableHelper.executeIdTableCreationStatements(IdTableHelper.java:67)[我们的app.war:5.1.0.Final]
在org.hibernate.hql.spi.id.GlobalTemporaryTableBulkIdStrategy.finishPreparion(GlobalTemporaryTableBulkIdStrategy.java:125)[我们的应用程序war:5.1.0.Final]
在org.hibernate.hql.spi.id.GlobalTemporaryTableBulkIdStrategy.finishPreparion(GlobalTemporaryTableBulkIdStrategy.java:42)[我们的应用程序war:5.1.0.Final]
在org.hibernate.hql.spi.id.AbstractMultiTableBulkIdStrategyImpl.prepare(AbstractMultiTableBulkIdStrategyImpl.java:88)[我们的应用程序war:5.1.0.Final]
在org.hibernate.internal.sessionfactorympl.(sessionfactorympl.java:451)[我们的app.war:5.1.0.Final]
我目前的理解是,在CICS上运行并使用JDBCType2驱动程序时,只有一些线程能够打开DB2连接。这将是应用程序线程(处理HTTP请求的线程)以及为
CICSExecutorService
提供服务的工作线程

目前的解决办法是:

  • 禁用
    JdbcEnvironmentInitiator
    中的JDBC元数据查找 设置
    hibernate.temp.use\u jdbc\u metadata\u defaults
    属性
    false
  • 将执行
    IdTableHelper#executeIdTableCreationStatements
    包装在
    Runnable
    中,并将其提交给
    CICSExecutorService
  • 你认为这个解决方案是足够的,适合生产吗?或者你用了不同的方法

    使用的版本:

    • 用于z/OS 5.3.0的CICS事务服务器
    • WebSphere Application Server 8.5.5.8
    • Hibernate 5.1.0


    更新:只是澄清一下,一旦我们的应用程序启动,它就可以毫无问题地查询DB2(在服务HTTP请求时)。该问题仅与启动有关。

    最近在服务刷新(2016年7月)中提供了对Liberty中JPA功能的CICS TS v5.3支持。在此更新之前,尝试在应用程序中运行JPA将导致与您描述的问题非常相似的问题

    尽管您运行的是hibernate,并且处于启用CICS的线程上,但它没有API环境(这将允许类型2 JDBC调用成功)。新的检测逻辑是专门为DB2JDBCType2驱动程序和JPA开发的(但不是唯一的)。此更新是在最近的服务刷新中发布的,可能会解决您看到的问题

    尝试应用:


    描述中说它是为了“标准模式自由”支持,但它包含上述其他开发。

    以下解决方案经测试正常

    其思想是使用执行SQL/DDL语句。以下扩展是通过
    hibernate.hql.bulk\u id\u策略
    属性注册的

    package org.hibernate.hql.spi.id.global;
    
    import java.util.concurrent.*;
    import org.hibernate.boot.spi.MetadataImplementor;
    import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
    import org.hibernate.engine.jdbc.spi.JdbcServices;
    import org.springframework.util.ClassUtils;
    import com.ibm.cics.server.*;
    
    public class CicsAwareGlobalTemporaryTableBulkIdStrategy extends GlobalTemporaryTableBulkIdStrategy {
    
        @Override
        protected void finishPreparation(JdbcServices jdbcServices, JdbcConnectionAccess connectionAccess, MetadataImplementor metadata, PreparationContextImpl context) {
            execute(() -> super.finishPreparation(jdbcServices, connectionAccess, metadata, context));
        }
    
        @Override
        public void release(JdbcServices jdbcServices, JdbcConnectionAccess connectionAccess) {
            execute(() -> super.release(jdbcServices, connectionAccess));
        }
    
        private void execute(Runnable runnable) {
            if (isCics() && IsCICS.getApiStatus() == IsCICS.CICS_REGION_BUT_API_DISALLOWED) {
                RunnableFuture<Void> task = new FutureTask<>(runnable, null);
                CICSExecutorService.runAsCICS(task);
                try {
                    task.get();
                } catch (InterruptedException | ExecutionException e) {
                    throw new RuntimeException("Failed to execute in a CICS API-enabled thread. " + e.getMessage(), e);
                }
            } else {
                runnable.run();
            }
        }
    
        private boolean isCics() {
            return ClassUtils.isPresent("com.ibm.cics.server.CICSExecutorService", null);
        }
    }
    
    尝试了几种替代方案:

  • 仅包装连接获取操作(
    org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl#getConnection
    )不起作用,因为在主线程中使用连接时已关闭连接
  • 包装整个应用程序启动(
    org.springframework.web.context.ContextLoaderListener#contextInitialized
    )会导致类加载问题

  • Edit:最终采用了自定义Hibernate的
    MultiTableBulkIdStrategy
    实现,该实现在启动时不运行任何SQL/DDL()。

    检查此@Gas您能更具体一点吗?我只是仔细检查了一下——我们的DB2数据源配置与给定文章中的配置完全相同(没有指定properties.DB2.jcc)?在该页面上有要配置的链接。我不是CICS专家,因此无法在这方面帮助您。@Gas谢谢。CICS端进行了配置(不能说是否正确),但一般来说,一旦启动webapp,DB2访问就可以正常工作,只有在启动期间我们才会遇到这个问题。更新了帖子以澄清这一点。
    package org.hibernate.hql.spi.id.global;
    
    import java.util.concurrent.*;
    import org.hibernate.boot.spi.MetadataImplementor;
    import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
    import org.hibernate.engine.jdbc.spi.JdbcServices;
    import org.springframework.util.ClassUtils;
    import com.ibm.cics.server.*;
    
    public class CicsAwareGlobalTemporaryTableBulkIdStrategy extends GlobalTemporaryTableBulkIdStrategy {
    
        @Override
        protected void finishPreparation(JdbcServices jdbcServices, JdbcConnectionAccess connectionAccess, MetadataImplementor metadata, PreparationContextImpl context) {
            execute(() -> super.finishPreparation(jdbcServices, connectionAccess, metadata, context));
        }
    
        @Override
        public void release(JdbcServices jdbcServices, JdbcConnectionAccess connectionAccess) {
            execute(() -> super.release(jdbcServices, connectionAccess));
        }
    
        private void execute(Runnable runnable) {
            if (isCics() && IsCICS.getApiStatus() == IsCICS.CICS_REGION_BUT_API_DISALLOWED) {
                RunnableFuture<Void> task = new FutureTask<>(runnable, null);
                CICSExecutorService.runAsCICS(task);
                try {
                    task.get();
                } catch (InterruptedException | ExecutionException e) {
                    throw new RuntimeException("Failed to execute in a CICS API-enabled thread. " + e.getMessage(), e);
                }
            } else {
                runnable.run();
            }
        }
    
        private boolean isCics() {
            return ClassUtils.isPresent("com.ibm.cics.server.CICSExecutorService", null);
        }
    }
    
    CICSExecutorService.runAsCICS(() -> { runnable.run(); return null; }).get();