2014-12-26 1 views
1

현재 데이터를 손상시키지 않고 (데이터베이스) java로 프로젝트를 마이그레이션하고 있습니다. 대부분의 데이터는 stored procedures (SP)을 통해 수집되며 데이터베이스에는 많은 양의 SP가 있습니다. 그래서, 각 SP를 실행하는 동안, 나는 그것을위한 클래스를 작성해야하는데, 그것은 엄청난 양의 클래스를 구축하고있다.서버에서 클라이언트로 json 통신을위한 일반적인 자바 클래스

따라서 이 클래스를 일반화하는 방법이 있으므로 모든 SP 결과를이 클래스로 변환 한 다음 클라이언트 측 (json)으로 변환 할 수 있습니까? 필드의

  1. 동적 번호 :

    다음 시나리오는 숨겨진 N 엄마 QN 있습니다.

  2. 동적 필드 이름.
  3. 유형은 문자열 일 수 있습니다 (이를 처리 할 수 ​​있음).

나는 데이터를 java.util.List으로 보내려고했지만 꽤 형식이 아닙니다. 인덱스를 가정하는 데이터를 가져와야합니다.

추신 : 동일한 것을 검색했지만 찾을 수 없습니다. 그리고 내가 너무 많이 요구하면 미안해.

답변

2

예, 이러한 일반적인 클래스를 작성할 수 있어야합니다. 다음은 작은 예제 클래스입니다. 이미 정의 된 저장 프로 시저가 있기 때문에 Firebird를 예제 데이터베이스 employee.fdb과 함께 사용합니다.

Firebird 서버에 연결하기 위해 Jaybird JDBC driver을 사용하고 jaybird-full-2.2.5.jar JAR 파일을 포함시킵니다.

JAVA에는 여러 가지 JSON 라이브러리가 있습니다. 스트리밍 모드 (XML 용 StaX와 같은)에서 여기 JSR 353: Java API for JSON Processing - Reference Implementation을 사용합니다. 따라서 두 번째 외부 JAR은 javax.json-1.0.4.jar입니다.

예제는 결과 집합을 반환하는 저장 프로 시저에서만 작동합니다. 출력 매개 변수가있는 저장 프로 시저의 경우 PreparedStatement 대신 CallableStatement을 사용해야합니다.

먼저 입력 매개 변수를 사용하여 특정 저장 프로 시저에 대한 일반 SQL 문을 만듭니다. 저장 프로 시저를 호출하려면 PreparedStatemend이 사용됩니다. 매개 변수는 개별 매개 변수 유형에 따라 설정됩니다. (절차 createSql()createStatement()) 방법 ResultSet.getMetaData()는 결과 집합의 열 정보를 가져 오는 데 사용됩니다 convertToJson() 절차에서는

(얼마나 많은 열, 열 이름 및 열 유형).

executeStoredProcedure() 메소드는 공개 API 메소드입니다.

main() 방법은 èmployee.fdb 데이터베이스에 연결하고 세 개의 저장 프로 시저 호출 GET_EMP_PROJ, MAIL_LABELORG_CHART을.

package com.genericsptojson; 

import java.io.ByteArrayOutputStream; 
import java.io.OutputStream; 
import java.io.UnsupportedEncodingException; 
import java.sql.Connection; 
import java.sql.DriverManager; 
import java.sql.PreparedStatement; 
import java.sql.ResultSet; 
import java.sql.ResultSetMetaData; 
import java.sql.SQLException; 
import java.sql.Types; 
import java.util.HashMap; 
import java.util.Map; 

import javax.json.Json; 
import javax.json.stream.JsonGenerator; 
import javax.json.stream.JsonGeneratorFactory; 

public class GenericSpToJson { 

    private static final String DB_URL = "jdbc:firebirdsql:localhost/3050:/var/lib/firebird/2.5/data/employee.fdb"; 
    private static final String DB_USER = "SYSDBA"; 
    private static final String DB_PWD = "***"; 

    private Connection con; 

    public GenericSpToJson(Connection con) { 
    this.con = con; 
    } 

    /** 
    * Creates the SQL to call the stored procedure. 
    * 
    * @param spName 
    *   Name of stored procecdure to call 
    * @param paramCount 
    *   number of input parameters 
    * @return SQL with placeholders for input parameters 
    */ 
    private String createSql(String spName, int paramCount) { 
    if(paramCount > 0) { 
     final StringBuilder params = new StringBuilder(); 
     boolean isFirst = true; 
     for(int i = 0; i < paramCount; i++) { 
     if(isFirst) { 
      isFirst = false; 
     } else { 
      params.append(", "); 
     } 
     params.append('?'); 
     } 
     return String.format("SELECT * FROM %s (%s)", spName, params.toString()); 
    } else { 
     return String.format("SELECT * FROM %s", spName); 
    } 
    } 

    /** 
    * Creates a PreparedStatement to call the stored procedure. This works only 
    * for stored procedures creating result sets. Stored procedures with OUT 
    * parameters should be handled by a CallableStatement instead. 
    * 
    * @param spName 
    *   The stored procedure name to be called. 
    * @param params 
    *   The input parameters. 
    * @return A prepared statement. All parameters are set. 
    * @throws SQLException 
    */ 
    private PreparedStatement createStatement(String spName, Object... params) throws SQLException { 
    final PreparedStatement stmt = con.prepareStatement(createSql(spName, params.length)); 
    for(int i = 0; i < params.length; i++) { 
     final Object param = params[i]; 
     if(param instanceof String) { 
     stmt.setString(i + 1, (String) param); 
     } else if(param instanceof Integer) { 
     stmt.setInt(i + 1, ((Integer) param).intValue()); 
     } else { 
     // Handle other param types ... 
     } 
    } 
    return stmt; 
    } 

    /** 
    * Converts the result set to JSON in streaming mode. 
    * 
    * @param spName 
    *   The stored procedure name. 
    * @param rs 
    *   The result set of the stored procedure call. 
    * @param out 
    *   The output stream to write the JSON into. 
    * @throws SQLException 
    */ 
    private void convertToJson(String spName, ResultSet rs, OutputStream out) throws SQLException { 
    // Get the result set meta data to obtain column information on the fly. 
    final ResultSetMetaData metaData = rs.getMetaData(); 

    // Create the JSON generator with pretty printing 
    final Map<String, Object> properties = new HashMap<String, Object>(1); 
    properties.put(JsonGenerator.PRETTY_PRINTING, true); 
    final JsonGeneratorFactory jsonGeneratorFactory = Json.createGeneratorFactory(properties); 
    final JsonGenerator generator = jsonGeneratorFactory.createGenerator(out); 
    generator.writeStartObject(); // root object 

    generator.write("storedProcedureName", spName); 
    generator.write("columnCount", metaData.getColumnCount()); 
    generator.writeStartArray("records"); // records array 
    while(rs.next()) { 
     generator.writeStartObject(); // record object 
     // Each record object contains one field for every column. 
     // The field name is the columns name. 
     for(int col = 1; col <= metaData.getColumnCount(); col++) { 
     final String fieldName = metaData.getColumnName(col); 
     switch(metaData.getColumnType(col)) { 
      case Types.INTEGER: 
      final int intValue = rs.getInt(col); 
      if(rs.wasNull()) { 
       generator.writeNull(fieldName); 
      } else { 
       generator.write(fieldName, intValue); 
      } 
      break; 
      case Types.VARCHAR: 
      case Types.CHAR: 
      String stringValue = rs.getString(col); 
      if(rs.wasNull()) { 
       generator.writeNull(fieldName); 
      } else { 
       if(metaData.getColumnType(col) == Types.CHAR) { 
       stringValue = stringValue.trim(); 
       } 
       generator.write(fieldName, stringValue); 
      } 
      break; 
      // Handle other types here 
      default: 
      System.out.println(String.format("Unhandled SQL type: %s", metaData.getColumnTypeName(col))); 
     } 
     } 
     generator.writeEnd(); // record object 
    } 
    generator.writeEnd(); // records array 
    generator.writeEnd(); // root object 
    generator.flush(); 
    generator.close(); 
    } 

    /** 
    * Executes the stored procedures with the given input parameters and creates 
    * JSON in streaming mode. 
    * 
    * @param spName 
    *   The name of the stored procedure. 
    * @param out 
    *   The output stream to write the generated JSON into. 
    * @param params 
    *   The stored procedure's parameters. 
    */ 
    public void executeStoredProcedure(String spName, OutputStream out, Object... params) { 
    PreparedStatement stmt = null; 
    ResultSet rs = null; 
    try { 
     stmt = createStatement(spName, params); 
     rs = stmt.executeQuery(); 
     convertToJson(spName, rs, out); 
    } catch (SQLException e) { 
     e.printStackTrace(); 
    } finally { 
     // Cleaning up ... 
     if(stmt != null) { 
     try { 
      stmt.close(); 
     } catch (SQLException e) { 
      e.printStackTrace(); 
     } 
     } 
     if(rs != null) { 
     try { 
      rs.close(); 
     } catch (SQLException e) { 
      e.printStackTrace(); 
     } 
     } 
    } 
    } 

    /** 
    * Convenience method to call the stored procedure and create a JSON string. 
    * This should only be called for short result sets. For longer result sets 
    * use {@link #executeStoredProcedure(String, OutputStream, Object...)} where 
    * it is not necessary to hold the entire JSON document in memory. 
    * 
    * @param spName 
    *   The name of the stored procedure to call. 
    * @param params 
    *   The stored procedure's parameters 
    * @return The stored procedure's call result as a JSON string. 
    * @throws UnsupportedEncodingException 
    */ 
    public String executeStoredProcedure(String spName, Object... params) throws UnsupportedEncodingException { 
    final ByteArrayOutputStream out = new ByteArrayOutputStream(); 
    executeStoredProcedure(spName, out, params); 
    return out.toString("UTF-8"); 
    } 


    public static void main(String[] args) { 
    Connection con = null; 
    try { 
     Class.forName("org.firebirdsql.jdbc.FBDriver"); 
     con = DriverManager.getConnection(DB_URL, DB_USER, DB_PWD); 

     final GenericSpToJson converter = new GenericSpToJson(con); 

     System.out.println("Executing stored procedure GET_EMP_PROJ (8):\n" 
      + converter.executeStoredProcedure("GET_EMP_PROJ", 8)); 
     System.out.println("\n\nExecuting stored procedure MAIL_LABEL (1015):\n" 
      + converter.executeStoredProcedure("MAIL_LABEL", 1015)); 
     System.out.println("\n\nExecuting stored procedure ORG_CHART:\n" 
      + converter.executeStoredProcedure("ORG_CHART")); 
    } catch (ClassNotFoundException e) { 
     e.printStackTrace(); 
    } catch (SQLException e) { 
     e.printStackTrace(); 
    } catch (UnsupportedEncodingException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
    if(con != null) { 
     try { 
     con.close(); 
     } catch (SQLException e) { 
     e.printStackTrace(); 
     } 
    } 
    }  
} 

출력 (단축)된다

Executing stored procedure GET_EMP_PROJ (8): 

{ 
    "storedProcedureName":"GET_EMP_PROJ", 
    "columnCount":1, 
    "records":[ 
     { 
      "PROJ_ID":"VBASE" 
     }, 
     { 
      "PROJ_ID":"GUIDE" 
     }, 
     { 
      "PROJ_ID":"MKTPR" 
     } 
    ] 
} 


Executing stored procedure MAIL_LABEL (1015): 

{ 
    "storedProcedureName":"MAIL_LABEL", 
    "columnCount":6, 
    "records":[ 
     { 
      "LINE1":"GeoTech Inc.", 
      "LINE2":"K.M. Neppelenbroek", 
      "LINE3":"P.0.Box 702", 
      "LINE4":"", 
      "LINE5":null, 
      "LINE6":"Netherlands 2514" 
     } 
    ] 
} 


Executing stored procedure ORG_CHART: 

{ 
    "storedProcedureName":"ORG_CHART", 
    "columnCount":5, 
    "records":[ 
     { 
      "HEAD_DEPT":null, 
      "DEPARTMENT":"Corporate Headquarters", 
      "MNGR_NAME":"Bender, Oliver H.", 
      "TITLE":"CEO", 
      "EMP_CNT":2 
     }, 
     { 
      "HEAD_DEPT":"Corporate Headquarters", 
      "DEPARTMENT":"Sales and Marketing", 
      "MNGR_NAME":"MacDonald, Mary S.", 
      "TITLE":"VP", 
      "EMP_CNT":2 
     }, 
     // ... SNIP ... 
     { 
      "HEAD_DEPT":"Corporate Headquarters", 
      "DEPARTMENT":"Finance", 
      "MNGR_NAME":"Steadman, Walter", 
      "TITLE":"CFO", 
      "EMP_CNT":2 
     } 
    ] 
} 
관련 문제