gpt4 book ai didi

java - ResultSet 到 JSON 的最有效转换?

转载 作者:IT老高 更新时间:2023-10-28 11:23:57 25 4
gpt4 key购买 nike

以下代码使用 JSONArrayResultSet 转换为 JSON 字符串和 JSONObject .

import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONException;

import java.sql.SQLException;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;

public class ResultSetConverter {
public static JSONArray convert( ResultSet rs )
throws SQLException, JSONException
{
JSONArray json = new JSONArray();
ResultSetMetaData rsmd = rs.getMetaData();

while(rs.next()) {
int numColumns = rsmd.getColumnCount();
JSONObject obj = new JSONObject();

for (int i=1; i<numColumns+1; i++) {
String column_name = rsmd.getColumnName(i);

if(rsmd.getColumnType(i)==java.sql.Types.ARRAY){
obj.put(column_name, rs.getArray(column_name));
}
else if(rsmd.getColumnType(i)==java.sql.Types.BIGINT){
obj.put(column_name, rs.getInt(column_name));
}
else if(rsmd.getColumnType(i)==java.sql.Types.BOOLEAN){
obj.put(column_name, rs.getBoolean(column_name));
}
else if(rsmd.getColumnType(i)==java.sql.Types.BLOB){
obj.put(column_name, rs.getBlob(column_name));
}
else if(rsmd.getColumnType(i)==java.sql.Types.DOUBLE){
obj.put(column_name, rs.getDouble(column_name));
}
else if(rsmd.getColumnType(i)==java.sql.Types.FLOAT){
obj.put(column_name, rs.getFloat(column_name));
}
else if(rsmd.getColumnType(i)==java.sql.Types.INTEGER){
obj.put(column_name, rs.getInt(column_name));
}
else if(rsmd.getColumnType(i)==java.sql.Types.NVARCHAR){
obj.put(column_name, rs.getNString(column_name));
}
else if(rsmd.getColumnType(i)==java.sql.Types.VARCHAR){
obj.put(column_name, rs.getString(column_name));
}
else if(rsmd.getColumnType(i)==java.sql.Types.TINYINT){
obj.put(column_name, rs.getInt(column_name));
}
else if(rsmd.getColumnType(i)==java.sql.Types.SMALLINT){
obj.put(column_name, rs.getInt(column_name));
}
else if(rsmd.getColumnType(i)==java.sql.Types.DATE){
obj.put(column_name, rs.getDate(column_name));
}
else if(rsmd.getColumnType(i)==java.sql.Types.TIMESTAMP){
obj.put(column_name, rs.getTimestamp(column_name));
}
else{
obj.put(column_name, rs.getObject(column_name));
}
}

json.put(obj);
}

return json;
}
}
  • 有更快的方法吗?
  • 有没有办法减少内存占用?

最佳答案

我认为有一种方法可以使用更少的内存(取决于数据基数的固定而非线性数量),但这意味着要更改方法签名。事实上,只要我们从 ResultSet 中获取 Json 数据,我们就可以直接在输出流上打印它们:已经写入的数据将被垃圾收集,因为我们不需要将它们保存在内存中的数组。

我使用接受类型适配器的 GSON。我编写了一个类型适配器来将 ResultSet 转换为 JsonArray,它看起来很像您的代码。我正在等待“Gson 2.1:目标于 2011 年 12 月 31 日”发布,它将具有“支持用户定义的流类型适配器”。然后我将我的适配器修改为流式适配器。


更新

正如 promise 的那样,我回来了,但不是和 Gson 在一起,而是和 Jackson 2 在一起。很抱歉迟到了(2 年)。

前言:使用较少内存的关键在于“服务器端”游标。使用这种游标(也称为 Java 开发人员的结果集),DBMS 在客户端继续读取时将数据增量发送到客户端(也称为驱动程序)。我认为 Oracle 游标默认是服务器端的。对于 MySQL > 5.0.2 在 connection url paramenter 查找 useCursorFetch .查看您最喜欢的 DBMS。

1:所以要使用更少的内存,我们必须:

  • 在后台使用服务器端光标
  • 使用结果集打开为 read only当然还有forward only ;
  • 避免将所有游标加载到列表(或JSONArray)中,而是将每一行直接写入输出行,这里的输出行是指输出流或编写器,也可以是包装输出流或编写器的 json 生成器。

2:正如 jackson 文档所说:

Streaming API is best performing (lowest overhead, fastest read/write; other 2 methods build on it)

3:我看到你在你的代码中使用了getInt、getBoolean。 getFloat... of ResultSet without wasNull .我希望这会产生问题。

4:我使用数组来缓存想法并避免每次迭代都调用 getter。虽然不喜欢 switch/case 构造,但我将它用于那个 int SQL Types

答案:尚未完全测试,基于Jackson 2.2 :

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.2.2</version>
</dependency>

ResultSetSerializer 对象指示 Jackson 如何序列化(将对象转换为 JSON)ResultSet。它使用内部的 Jackson Streaming API。这里是一个测试的代码:

SimpleModule module = new SimpleModule();
module.addSerializer(new ResultSetSerializer());

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(module);

[ . . . do the query . . . ]
ResultSet resultset = statement.executeQuery(query);

// Use the DataBind Api here
ObjectNode objectNode = objectMapper.createObjectNode();

// put the resultset in a containing structure
objectNode.putPOJO("results", resultset);

// generate all
objectMapper.writeValue(stringWriter, objectNode);

当然还有 ResultSetSerializer 类的代码:

public class ResultSetSerializer extends JsonSerializer<ResultSet> {

public static class ResultSetSerializerException extends JsonProcessingException{
private static final long serialVersionUID = -914957626413580734L;

public ResultSetSerializerException(Throwable cause){
super(cause);
}
}

@Override
public Class<ResultSet> handledType() {
return ResultSet.class;
}

@Override
public void serialize(ResultSet rs, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {

try {
ResultSetMetaData rsmd = rs.getMetaData();
int numColumns = rsmd.getColumnCount();
String[] columnNames = new String[numColumns];
int[] columnTypes = new int[numColumns];

for (int i = 0; i < columnNames.length; i++) {
columnNames[i] = rsmd.getColumnLabel(i + 1);
columnTypes[i] = rsmd.getColumnType(i + 1);
}

jgen.writeStartArray();

while (rs.next()) {

boolean b;
long l;
double d;

jgen.writeStartObject();

for (int i = 0; i < columnNames.length; i++) {

jgen.writeFieldName(columnNames[i]);
switch (columnTypes[i]) {

case Types.INTEGER:
l = rs.getInt(i + 1);
if (rs.wasNull()) {
jgen.writeNull();
} else {
jgen.writeNumber(l);
}
break;

case Types.BIGINT:
l = rs.getLong(i + 1);
if (rs.wasNull()) {
jgen.writeNull();
} else {
jgen.writeNumber(l);
}
break;

case Types.DECIMAL:
case Types.NUMERIC:
jgen.writeNumber(rs.getBigDecimal(i + 1));
break;

case Types.FLOAT:
case Types.REAL:
case Types.DOUBLE:
d = rs.getDouble(i + 1);
if (rs.wasNull()) {
jgen.writeNull();
} else {
jgen.writeNumber(d);
}
break;

case Types.NVARCHAR:
case Types.VARCHAR:
case Types.LONGNVARCHAR:
case Types.LONGVARCHAR:
jgen.writeString(rs.getString(i + 1));
break;

case Types.BOOLEAN:
case Types.BIT:
b = rs.getBoolean(i + 1);
if (rs.wasNull()) {
jgen.writeNull();
} else {
jgen.writeBoolean(b);
}
break;

case Types.BINARY:
case Types.VARBINARY:
case Types.LONGVARBINARY:
jgen.writeBinary(rs.getBytes(i + 1));
break;

case Types.TINYINT:
case Types.SMALLINT:
l = rs.getShort(i + 1);
if (rs.wasNull()) {
jgen.writeNull();
} else {
jgen.writeNumber(l);
}
break;

case Types.DATE:
provider.defaultSerializeDateValue(rs.getDate(i + 1), jgen);
break;

case Types.TIMESTAMP:
provider.defaultSerializeDateValue(rs.getTime(i + 1), jgen);
break;

case Types.BLOB:
Blob blob = rs.getBlob(i);
provider.defaultSerializeValue(blob.getBinaryStream(), jgen);
blob.free();
break;

case Types.CLOB:
Clob clob = rs.getClob(i);
provider.defaultSerializeValue(clob.getCharacterStream(), jgen);
clob.free();
break;

case Types.ARRAY:
throw new RuntimeException("ResultSetSerializer not yet implemented for SQL type ARRAY");

case Types.STRUCT:
throw new RuntimeException("ResultSetSerializer not yet implemented for SQL type STRUCT");

case Types.DISTINCT:
throw new RuntimeException("ResultSetSerializer not yet implemented for SQL type DISTINCT");

case Types.REF:
throw new RuntimeException("ResultSetSerializer not yet implemented for SQL type REF");

case Types.JAVA_OBJECT:
default:
provider.defaultSerializeValue(rs.getObject(i + 1), jgen);
break;
}
}

jgen.writeEndObject();
}

jgen.writeEndArray();

} catch (SQLException e) {
throw new ResultSetSerializerException(e);
}
}
}

关于java - ResultSet 到 JSON 的最有效转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6514876/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com