使用 Java JDBC 写入时 VSAM 文件锁定

Posted

技术标签:

【中文标题】使用 Java JDBC 写入时 VSAM 文件锁定【英文标题】:VSAM file locking when writing to it using Java JDBC 【发布时间】:2015-12-10 15:29:48 【问题描述】:

这是我第一次尝试读写 VSAM 文件。我所做的是:

    使用 VSE Navigator 为文件创建了地图 将 Java beans VSE 连接器库添加到我的 eclipse Java 项目中 使用下面显示的代码写入和读取 KSDS 文件。

读取文件不是问题,但是当我尝试写入文件时,它只有在我进入大型机并在运行我的 java 程序之前关闭文件时才有效,但它会锁定文件大约一个小时。您无法在大型机上打开该文件或对其进行任何操作。

任何人都可以帮助解决这个问题。是否需要为大型机上的文件设置特殊设置?为什么您首先需要关闭 CICS 上的文件才能对其进行写入?为什么它在写入文件后锁定文件?

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.sql.*;
public class testVSAM 

public static void main(String argv[])
    Integer test = Integer.valueOf(2893);
    String vsamCatalog = "VSESP.USER.CATALOG";
    String FlightCluster = "FLIGHT.ORDERING.FLIGHTS";       
    String FlightMapName = "FLIGHT.TEST2.MAP";
    try

        String ipAddr = "10.1.1.1";                     
        String userID = "USER1";            
        String password = "PASSWORD"; 

        java.sql.Connection jdbcCon;            
        java.sql.Driver jdbcDriver = (java.sql.Driver) Class.forName(
        "com.ibm.vse.jdbc.VsamJdbcDriver").newInstance();
        // Build the URL to use to connect
        String url = "jdbc:vsam:"+ipAddr;
        // Assign properties for the driver
        java.util.Properties prop = new java.util.Properties();
        prop.put("port", test);
        prop.put("user", userID);
        prop.put("password", password);
        // Connect to the driver
        jdbcCon = DriverManager.getConnection(url,prop);

        try 
            java.sql.PreparedStatement pstmt = jdbcCon.prepareStatement(
            "INSERT INTO "+vsamCatalog+"\\"+FlightCluster+"\\"+FlightMapName+
            " (RS_SERIAL1,RS_SERIAL2,RS_QTY1,RS_QTY2,RS_UPDATE,RS_UPTIME,RS_EMPNO,RS_PRINTFLAG,"+
            "RS_PART_S,RS_PART_IN_A_P,RS_FILLER)"+" VALUES(?,?,?,?,?,?,?,?,?,?,?)");
            //pstmt.setString(1, "12345678901234567890123003");
            pstmt.setString(1, "1234567890");
            pstmt.setString(2,"1234567890123");
            pstmt.setInt(3,00);
            pstmt.setInt(4,003);
            pstmt.setString(5,"151209");
            pstmt.setString(6, "094435");
            pstmt.setString(7,"09932");
            pstmt.setString(8,"P");
            pstmt.setString(9,"Y");
            pstmt.setString(10,"Y");
            pstmt.setString(11," ");
            // Execute the query
            int num = pstmt.executeUpdate();
            System.out.println(num);
            pstmt.close();

            
            catch (SQLException t)
            

                System.out.println(t.toString());                       
             

        try
        
        // Get a statement
        java.sql.Statement stmt = jdbcCon.createStatement();
        // Execute the query ...
        java.sql.ResultSet rs = stmt.executeQuery(
        "SELECT * FROM "+vsamCatalog+"\\"+FlightCluster+"\\"+FlightMapName);

        while (rs.next())
                                                   
        System.out.println(rs.getString("RS_SERIAL1") +  " " + rs.getString("RS_SERIAL2")+  " " + rs.getString("RS_UPTIME")+ " " + rs.getString("RS_UPDATE"));
        
        rs.close();
        stmt.close();
        
        catch (SQLException t)
        

         
    
    catch (Exception e)
    
        // do something appropriate with the exception, *at least*:
        e.printStackTrace();
     


注意:操作系统是 z/VSE

【问题讨论】:

那么你的问题到底是什么?为什么写入文件需要排他锁?为什么写这么久?请尝试更具体。 我更新了我的问题。但我的问题是。为什么我需要先关闭 CICS 上的文件才能写入文件。以及为什么在我写入文件后文件锁定(无法打开、读取或写入)? 我没有看到您关闭与该文件的连接 - 这可能会使其保持打开和锁定状态。 一月感谢您的帮助! :)。我们解决了这个问题。问题是 JDBC 使用的服务器端(大型机)上的 VSE 连接器使用批处理程序。 CISC 文件是使用只有 CICS 程序可以写入而不是批处理程序的选项创建的。我们使用批处理程序可以写入的属性重新定义文件,现在它可以工作了。如果术语或解释不是关于大型机的最佳,我是一名 PC 程序员,非常抱歉。 如果你花时间回答你自己的问题(并接受它!)那就太好了,所以下一个人有一些关于如何通过搜索解决这个问题的信息。 【参考方案1】:

对原始问题的简短回答是 KSDS VSAM 不是 DBMS。

正如您所发现的,您可以定义 VSAM 文件,以便可以从批处理和 CICS 更新它,但正如 @BillWoodger 指出的那样,您必须自己序列化更新。

另一种方法是从 CICS 区域进行所有更新,并让您的 Java 应用程序向 CICS 发送 REST 或 SOAP 或 MQ 消息以请求其更新。这确实需要有一个 CICS 程序来捕获来自 Java 应用程序的请求并执行更新。

【讨论】:

【参考方案2】:

z/VSE 下的 IBM 大型机具有运行不同作业的不同分区。例如分区 F7 CICS、分区 F8 Batch Jobs、ETC。

当您定义一个新的 VSAM 文件时,您必须设置文件的 SHAREOPTIONS。当我定义文件时,我设置了 SHAREOPTIONS (2 3)。 2 表示只有一个分区可以写入文件。

因此,当从 Java 调用的批处理程序(在与 CICS 分区不同的分区中)试图写入文件时,它无法写入文件,除非我先在 CICS 中关闭文件。

为了修复它,我使用 SHAREOPTIONS (4 3) 重新定义了 CICS 文件。 4 表示 Mainframe 的多个分区可以写入。解决问题

下面是你设置SHAREOPTION的部分定义代码:

* $$ JOB JNM=DEFFI,CLASS=9,DISP=D,PRI=9         
* $$ LST CLASS=X,DISP=H,PRI=2,REMOTE=0,USER=JAVI
// JOB DEFFI                                    
// EXEC IDCAMS,SIZE=AUTO                                                         
DEFINE  CLUSTER -                            
          ( -                                
          NAME (FLIGHT.ORDERING.FLIGHTS) -  
          RECORDS (2000 1000) -              
          INDEXED -                          
          KEYS (26 0) -                      
          RECORDSIZE (128 128) -             
          SHAREOPTIONS (4 3) -               
          VOLUMES (SYSWKE) -                 
          ) -                                
          .
          .  
          .              

【讨论】:

慢下来:“使用选项 3 和 4,您负责维护程序访问的数据的读写完整性。这些选项要求您的程序在共享时使用 ENQ/DEQ 来维护数据完整性数据集,包括 OPEN 和 CLOSE 处理。忽略写入完整性准则的用户程序可能会导致 VSAM 程序检查、丢失或无法访问记录、无法纠正的数据集故障以及其他不可预知的结果。这些选项对共享数据集。” 嘿比尔,我应该提一下我是 PC 程序员而不是大型机程序员。当您谈论我使用 ENQ/DEQ 的程序时,您是在谈论读取/写入 VSAM 文件的 CISC 程序吗? 如果两个“程序”对同一个文件有更新访问权限,他们需要有代码来对资源进行排队,完成工作,然后对资源进行解除排队。否则充其量您会不时丢失数据,最坏的情况是您会损坏无法修复的文件。将消息从您的 Java 发送到 CICS(注意字母顺序)程序以进行更新是保持简单的一种方法。另请注意,使用 SHAREOPTIONS 3 或 4,您可能/将会降低性能,即使只是读取文件也是如此。 对于大型机新手,您需要依赖大型机同事和技术支持。他们会像任何东西一样快速反弹,所以无论如何你都需要一个不同的解决方案。所以在设计的某个地方,这应该已经被覆盖了。如果您想从不同的“程序”进行多个同时更新(松散地使用术语,将 CICS 视为一个程序),那么您需要在两个/所有程序中处理它。 SHAREOPTIONS 4 有利于多次更新,但数据完整性取决于用户(程序员)。

以上是关于使用 Java JDBC 写入时 VSAM 文件锁定的主要内容,如果未能解决你的问题,请参考以下文章

在 VSAM 文件上打印报告

使用 Python 访问 VSAM 文件?

编写从单独的 vsam 文件中提取信息的 Cobol 程序时遇到问题

如何计算分配给 VSAM 文件的空间

是否可以强制删除另一个作业/用户使用的 VSAM 文件?

是否有将 VSAM 文件作为 tbble 或数据框导入的 R 包?