用于从服务器到客户端的json通信的公共java类
我目前正在将一个项目迁移到java,保持数据完整(数据库)。大多数数据是通过存储过程(SP)获取的,数据库中有大量SP。 因此,在执行每个SP时,我必须为此编写一个类,这将建立一大堆类 因此,是否有任何方法来泛化该类,以便我可以将每个SP结果转换为该类,然后转换为客户端(如用于从服务器到客户端的json通信的公共java类,java,json,stored-procedures,Java,Json,Stored Procedures,我目前正在将一个项目迁移到java,保持数据完整(数据库)。大多数数据是通过存储过程(SP)获取的,数据库中有大量SP。 因此,在执行每个SP时,我必须为此编写一个类,这将建立一大堆类 因此,是否有任何方法来泛化该类,以便我可以将每个SP结果转换为该类,然后转换为客户端(如json)? 以下场景是隐藏的n ma qn: 动态字段数 动态字段名 类型可以是字符串 (我们可以解决这个问题) 我曾尝试以java.util.List的形式发送数据,但格式不太好。必须采用假设索引的数据 PS:我已经搜索过
json
)?
以下场景是隐藏的n ma qn:
java.util.List
的形式发送数据,但格式不太好。必须采用假设索引的数据
PS:我已经搜索过了,但是没有找到。如果我要求的太多,我也很抱歉。是的,应该可以编写这样一个泛型类。这里有一个小示例类作为您的起点。我将Firebird用于示例数据库
employee.fdb
,因为已经定义了一些存储过程
因此,为了连接Firebird服务器,我使用并包含jaybird-full-2.2.5.jar
jar文件
JAVA有几种不同的JSON库。我在流模式下使用here(如StaX for XML)。所以这里的第二个外部JAR是javax.json-1.0.4.JAR
我的示例仅适用于返回结果集的存储过程。对于具有输出参数的存储过程,应使用CallableStatement
,而不是PreparedStatement
首先,为特定存储过程及其输入参数创建一个通用SQL语句。要调用存储过程,请使用PreparedStatemend
。参数根据各个参数类型进行设置。(过程createSql()
和createStatement()
)
在过程convertToJson()
中,方法ResultSet.getMetaData()
用于获取结果集的列信息(列数、列名和列类型)
executeStoredProcedure()
方法是要调用的公共API方法
main()
方法连接到èemployee.fdb
数据库并调用三个存储过程:GET_EMP_PROJ
、MAIL_LABEL
和ORG_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
}
]
}