การแปลง ResultSet เป็น JSON ที่มีประสิทธิภาพสูงสุด?


109

รหัสต่อไปนี้แปลงResultSetเป็นสตริง JSON ใช้และJSONArrayJSONObject

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;
  }
}
  • มีวิธีที่เร็วกว่านี้ไหม
  • มีวิธีที่ใช้หน่วยความจำน้อยหรือไม่?

1
การดำเนินแตกต่างกันcode.google.com/p/bonex-homerunning/source/browse/trunk/...
Leif Gruenwoldt

1
การใช้งาน java.sql.Types.ARRAY ใช้ไม่ได้สำหรับฉันโดยใช้ postgresql (อาร์เรย์ถูกวางเป็นสตริงโดยใช้ "{... }" สิ้นสุดการเปลี่ยนบรรทัด "obj.put (column_name, rs.getArray (column_name) ); "to" Array array = rs.getArray (column_name); if (array! = null) obj.put (column_name, new JSONArray (array.getArray ())); "
molecular

หากประสิทธิภาพเป็นปัญหาหลักคุณไม่ควรใช้ JSON API นี้ แต่ควรใช้ไลบรารีสตรีมมิ่งที่เขียน JSON โดยไม่จำเป็นต้องสร้างออบเจ็กต์หน่วยความจำของข้อมูลทั้งหมด (ซึ่งคุณสามารถย้อนกลับไปดู / ค้นหาสิ่งต่างๆในโครงสร้างได้) ที่กล่าวมาฉันจะตรวจสอบให้แน่ใจว่าคุณมีปัญหาด้านประสิทธิภาพจริงก่อนที่จะทำเช่นนั้น
Sebastiaan van den Broek

3
มีข้อผิดพลาดในข้อมูลโค้ดของคุณ java.sql.Types.BIGINTมีขนาด 8 ไบต์ดังนั้นต้องอ่านด้วยrs.getLong()notrs.getInt()
polarfish

3
ขอบคุณสำหรับการโหลดสิ่งนี้ คุณช่วยฉันทำงานได้หลายชั่วโมง
DRich

คำตอบ:


23

JIT Compiler น่าจะทำให้เร็วมากเนื่องจากเป็นเพียงแค่กิ่งก้านและการทดสอบพื้นฐาน คุณอาจทำให้มันดูหรูหราขึ้นได้ด้วยการค้นหา HashMap เพื่อโทรกลับ แต่ฉันสงสัยว่ามันจะเร็วกว่านี้ สำหรับหน่วยความจำมันค่อนข้างบางเหมือนเดิม

ฉันสงสัยว่ารหัสนี้เป็นคอขวดที่สำคัญสำหรับหน่วยความจำหรือประสิทธิภาพ คุณมีเหตุผลที่แท้จริงที่จะพยายามเพิ่มประสิทธิภาพหรือไม่?


ฉันกำลังใส่ซอร์สโค้ดในเฟรมเวิร์กโอเพนซอร์สดังนั้นฉันจึงไม่รู้ว่าจะใช้ทำอะไร ดังนั้นฉันจึงพยายามทำให้มีประสิทธิภาพมากที่สุด
Devin Dixon

1
@DevinDixon: มีกรอบงานหรือไม่ มีอะไรเช่นรหัสในคำถามของคุณอยู่แล้วใน repo โอเพนซอร์สที่ไหนสักแห่ง?

34

ฉันคิดว่ามีวิธีที่จะใช้หน่วยความจำน้อยลง (จำนวนคงที่และไม่ใช่เชิงเส้นขึ้นอยู่กับจำนวนข้อมูล) แต่หมายความว่าจะเปลี่ยนลายเซ็นของวิธีการ ในความเป็นจริงเราอาจพิมพ์ข้อมูล Json โดยตรงบนเอาต์พุตสตรีมทันทีที่เราดึงข้อมูลจาก ResultSet: ข้อมูลที่เขียนแล้วจะถูกเก็บรวบรวมเนื่องจากเราไม่ต้องการอาร์เรย์ที่เก็บไว้ในหน่วยความจำ

ฉันใช้ GSON ที่ยอมรับอะแดปเตอร์ประเภท ฉันเขียนอะแดปเตอร์ประเภทเพื่อแปลง ResultSet เป็น JsonArray และดูเหมือนโค้ดของคุณมาก ฉันกำลังรอรุ่น "Gson 2.1: Targeted 31 ธันวาคม 2011" ซึ่งจะมี "การสนับสนุนสำหรับอะแดปเตอร์ประเภทสตรีมมิงที่ผู้ใช้กำหนดเอง" จากนั้นฉันจะแก้ไขอะแดปเตอร์เป็นอะแดปเตอร์สตรีม


อัปเดต

ตามที่สัญญาไว้ฉันจะกลับมา แต่ไม่ใช่กับ Gson แทนที่จะเป็นกับแจ็คสัน 2 ขอโทษที่มาสาย (จาก 2 ปี)

คำนำ:กุญแจสำคัญในการใช้หน่วยความจำน้อยลงของผลลัพธ์ itsef อยู่ในเคอร์เซอร์ "ฝั่งเซิร์ฟเวอร์" ด้วยเคอร์เซอร์ประเภทนี้ (aka resultset to Java devs) DBMS จะส่งข้อมูลไปยังไคลเอนต์ (aka driver) แบบเพิ่มขึ้นเมื่อไคลเอนต์ไปข้างหน้าพร้อมกับการอ่าน ฉันคิดว่าเคอร์เซอร์ Oracle เป็นฝั่งเซิร์ฟเวอร์โดยค่าเริ่มต้น สำหรับ MySQL> 5.0.2 มองหา useCursorFetch ที่เชื่อมต่อ URL paramenter ตรวจสอบเกี่ยวกับ DBMS ที่คุณชื่นชอบ

1:ดังนั้นเพื่อใช้หน่วยความจำน้อยลงเราต้อง:

  • ใช้เคอร์เซอร์ฝั่งเซิร์ฟเวอร์ด้านหลังฉาก
  • ใช้ ResultSet เปิดอ่านเท่านั้นและแน่นอนไปข้างหน้าเท่านั้น ;
  • หลีกเลี่ยงการโหลดเคอร์เซอร์ทั้งหมดในรายการ (หรือ a JSONArray) แต่เขียนแต่ละแถวโดยตรงบนบรรทัดเอาต์พุตโดยที่สำหรับบรรทัดเอาต์พุตฉันหมายถึงสตรีมเอาต์พุตหรือตัวเขียนหรือตัวสร้าง json ที่ห่อสตรีมเอาต์พุตหรือตัวเขียน

2:ตามที่เอกสารของ Jackson กล่าวว่า:

Streaming API มีประสิทธิภาพดีที่สุด (ค่าใช้จ่ายต่ำสุดอ่าน / เขียนเร็วที่สุดอีก 2 วิธีสร้างขึ้นมา)

3:ฉันเห็นคุณในรหัสของคุณใช้ getInt, getBoolean getFloat ... ของ ResultSet โดยไม่ต้องwasNull ฉันคาดหวังว่าสิ่งนี้จะทำให้เกิดปัญหาได้

4:ฉันใช้อาร์เรย์เพื่อคิดแคชและเพื่อหลีกเลี่ยงการเรียก getters การทำซ้ำแต่ละครั้ง แม้ว่าจะไม่ใช่แฟนของโครงสร้างสวิตช์ / เคส แต่ฉันก็ใช้มันสำหรับintSQL Typesนั้น

คำตอบ:ยังไม่ได้รับการทดสอบอย่างสมบูรณ์มันขึ้นอยู่กับJackson 2.2 :

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

ResultSetSerializerวัตถุสั่งให้แจ็คสันเกี่ยวกับวิธีการอันดับ (tranform วัตถุเพื่อ 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);
        }
    }
}

27

สองสิ่งที่จะทำให้เร็วขึ้นคือ:

ย้ายสายของคุณrsmd.getColumnCount()ออกจากลูป while จำนวนคอลัมน์ไม่ควรแตกต่างกันในแต่ละแถว

สำหรับคอลัมน์แต่ละประเภทคุณจะเรียกสิ่งนี้:

obj.put(column_name, rs.getInt(column_name));

จะเร็วกว่าเล็กน้อยในการใช้ดัชนีคอลัมน์เพื่อดึงค่าคอลัมน์:

obj.put(column_name, rs.getInt(i));

กำหนดString column_name;นอกลูป while ด้วย
Charney Kaye

22

วิธีแก้ปัญหาที่ง่ายกว่า (ขึ้นอยู่กับรหัสที่เป็นปัญหา):

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; i++) {
    String column_name = rsmd.getColumnName(i);
    obj.put(column_name, rs.getObject(column_name));
  }
  json.put(obj);
}
return json;

3
ดี แต่มีข้อผิดพลาดกับ DATETIME และ TIMESTAMP (ไม่ได้เพิ่มเครื่องหมาย
วรรคตอน

ดีและเรียบง่าย
Anoop LL

10

คุณสามารถใช้jOOQสำหรับงาน คุณไม่จำเป็นต้องใช้คุณสมบัติทั้งหมดของ jOOQ เพื่อใช้ประโยชน์จากส่วนขยาย JDBC ที่มีประโยชน์ ในกรณีนี้เพียงเขียน:

String json = DSL.using(connection).fetch(resultSet).formatJSON();

วิธีการ API ที่เกี่ยวข้องที่ใช้ ได้แก่ :

การจัดรูปแบบผลลัพธ์จะมีลักษณะดังนี้:

{"fields":[{"name":"field-1","type":"type-1"},
           {"name":"field-2","type":"type-2"},
           ...,
           {"name":"field-n","type":"type-n"}],
 "records":[[value-1-1,value-1-2,...,value-1-n],
            [value-2-1,value-2-2,...,value-2-n]]}

คุณยังสามารถสร้างการจัดรูปแบบของคุณเองได้อย่างง่ายดายผ่าน Result.map(RecordMapper)

โดยพื้นฐานแล้วสิ่งนี้ทำเช่นเดียวกับรหัสของคุณโดยหลีกเลี่ยงการสร้างออบเจ็กต์ JSON "สตรีมมิ่ง" ไปยังไฟล์ StringBuilder . ฉันจะบอกว่าค่าใช้จ่ายในการแสดงควรมีเล็กน้อยในทั้งสองกรณี

(ข้อจำกัดความรับผิดชอบ: ฉันทำงานให้กับ บริษัท ที่อยู่เบื้องหลัง jOOQ)


ยอดเยี่ยมมาก แต่ฉันมีปัญหาในการแยกวิเคราะห์สตริงผลลัพธ์ เมื่อค่าบางค่ามีเครื่องหมายอัญประกาศตัววิเคราะห์ไม่สามารถทำงานได้อย่างถูกต้อง: ฉันคิดว่าควรใช้เครื่องหมายอัญประกาศภายในค่า ( "ถึง\") เพื่อสร้างสตริง JSON ที่ถูกต้อง นี่เป็นจุดบกพร่องของformatJSON()ฟังก์ชันหรือไม่? หรือฉันขาดอะไรไป?
Oneiros

@Oneiros: jOOQ ควรหลีกเลี่ยงเครื่องหมายคำพูดเหล่านั้นอย่างถูกต้อง ... ดีที่สุดถามคำถามใหม่ (พร้อมรายละเอียด) หรือรายงานข้อผิดพลาด: github.com/jOOQ/jOOQ/issues/new
Lukas Eder

ในตัวอย่างของคุณ resultSet ใช้ในfetch(resultSet)อะไร? ไม่ได้กำหนดไว้ที่ใดก็ได้ และถ้าฉันได้รับ JDBC ResultSetก่อนที่จะดึงข้อมูลคือDSL.using(connection)อะไร? ทำไมต้องมีการเชื่อมต่อ? :)
Nikola Lošić

1
@ NikolaLošić: ดีคำถามที่ถามเกี่ยวกับการใช้ JDBC ดังนั้นฉันคิดว่ามีข้อสงสัยเกี่ยวกับการไม่มีResultSet ResultSetอันที่จริงมันดูไม่ชัดเจนว่าทำไมถึงconnectionต้องการที่นี่ หากคุณใช้ jOOQ คุณจะมีDSLContext(ผลลัพธ์ของDSL.using(connection)หรือที่คล้ายกัน) อยู่รอบ ๆ ตัวคุณอย่างไรก็ตาม
Lukas Eder

ไลบรารี JOOQ ที่ถูกต้องควรรวมไว้คืออะไร? ฉันพยายามหลายครั้ง แต่ทุกคนให้ข้อผิดพลาด Class not found with DSL reference Thnks
Lorenzo Barbagli

7

นอกเหนือจากคำแนะนำของ @Jim Cook อีกความคิดหนึ่งคือการใช้สวิตช์แทน if-elses:

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);

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

  json.put(obj);
}

4
การวนกลับไปข้างหลัง (เปรียบเทียบศูนย์ดัชนี) ก็เร็วกว่าเช่นกัน (กว่าการเปรียบเทียบดัชนีกับนิพจน์)
Dave Jarvis

4

คำตอบนี้อาจไม่ได้ผลดีที่สุด แต่เป็นแบบไดนามิก การจับคู่ JDBC ดั้งเดิมกับไลบรารี Gson ของ Google ฉันสามารถแปลงจากผลลัพธ์ SQL เป็นสตรีม JSON ได้อย่างง่ายดาย

ฉันได้รวมตัวแปลงไฟล์คุณสมบัติ DB ตัวอย่างการสร้างตาราง SQL และไฟล์ Gradle build (ที่ใช้การอ้างอิง)

QueryApp.java

import java.io.PrintWriter;

import com.oracle.jdbc.ResultSetConverter;

public class QueryApp {
    public static void main(String[] args) {
        PrintWriter writer = new PrintWriter(System.out);
        String dbProps = "/database.properties";
        String indent = "    ";

        writer.println("Basic SELECT:");
        ResultSetConverter.queryToJson(writer, dbProps, "SELECT * FROM Beatles", indent, false);

        writer.println("\n\nIntermediate SELECT:");
        ResultSetConverter.queryToJson(writer, dbProps, "SELECT first_name, last_name, getAge(date_of_birth) as age FROM Beatles", indent, true);
    }
}

ResultSetConverter.java

package com.oracle.jdbc;

import java.io.*;
import java.lang.reflect.Type;
import java.sql.*;
import java.util.*;

import com.google.common.reflect.TypeToken;
import com.google.gson.GsonBuilder;
import com.google.gson.stream.JsonWriter;

public class ResultSetConverter {
    public static final Type RESULT_TYPE = new TypeToken<List<Map<String, Object>>>() {
        private static final long serialVersionUID = -3467016635635320150L;
    }.getType();

    public static void queryToJson(Writer writer, String connectionProperties, String query, String indent, boolean closeWriter) {
        Connection conn = null;
        Statement stmt = null;
        GsonBuilder gson = new GsonBuilder();
        JsonWriter jsonWriter = new JsonWriter(writer);

        if (indent != null) jsonWriter.setIndent(indent);

        try {
            Properties props = readConnectionInfo(connectionProperties);
            Class.forName(props.getProperty("driver"));

            conn = openConnection(props);
            stmt = conn.createStatement();

            gson.create().toJson(QueryHelper.select(stmt, query), RESULT_TYPE, jsonWriter);

            if (closeWriter) jsonWriter.close();

            stmt.close();
            conn.close();
        } catch (SQLException se) {
            se.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
            try {
                if (stmt != null) stmt.close();
            } catch (SQLException se2) {
            }
            try {
                if (conn != null) conn.close();
            } catch (SQLException se) {
                se.printStackTrace();
            }
            try {
                if (closeWriter && jsonWriter != null) jsonWriter.close();
            } catch (IOException ioe) {
                ioe.printStackTrace();
            }
        }
    }

    private static Properties readConnectionInfo(String resource) throws IOException {
        Properties properties = new Properties();
        InputStream in = ResultSetConverter.class.getResourceAsStream(resource);
        properties.load(in);
        in.close();

        return properties;
    }

    private static Connection openConnection(Properties connectionProperties) throws IOException, SQLException {
        String database = connectionProperties.getProperty("database");
        String username = connectionProperties.getProperty("username");
        String password = connectionProperties.getProperty("password");

        return DriverManager.getConnection(database, username, password);
    }
}

QueryHelper.java

package com.oracle.jdbc;

import java.sql.*;
import java.text.*;
import java.util.*;

import com.google.common.base.CaseFormat;

public class QueryHelper {
    static DateFormat DATE_FORMAT = new SimpleDateFormat("YYYY-MM-dd");

    public static List<Map<String, Object>> select(Statement stmt, String query) throws SQLException {
        ResultSet resultSet = stmt.executeQuery(query);
        List<Map<String, Object>> records = mapRecords(resultSet);

        resultSet.close();

        return records;
    }

    public static List<Map<String, Object>> mapRecords(ResultSet resultSet) throws SQLException {
        List<Map<String, Object>> records = new ArrayList<Map<String, Object>>();
        ResultSetMetaData metaData = resultSet.getMetaData();

        while (resultSet.next()) {
            records.add(mapRecord(resultSet, metaData));
        }

        return records;
    }

    public static Map<String, Object> mapRecord(ResultSet resultSet, ResultSetMetaData metaData) throws SQLException {
        Map<String, Object> record = new HashMap<String, Object>();

        for (int c = 1; c <= metaData.getColumnCount(); c++) {
            String columnType = metaData.getColumnTypeName(c);
            String columnName = formatPropertyName(metaData.getColumnName(c));
            Object value = resultSet.getObject(c);

            if (columnType.equals("DATE")) {
                value = DATE_FORMAT.format(value);
            }

            record.put(columnName, value);
        }

        return record;
    }

    private static String formatPropertyName(String property) {
        return CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, property);
    }
}

database.properties

driver=com.mysql.jdbc.Driver
database=jdbc:mysql://localhost/JDBC_Tutorial
username=root
password=

JDBC_Tutorial.sql

-- phpMyAdmin SQL Dump
-- version 4.5.1
-- http://www.phpmyadmin.net
--
-- Host: 127.0.0.1
-- Generation Time: Jan 12, 2016 at 07:40 PM
-- Server version: 10.1.8-MariaDB
-- PHP Version: 5.6.14

SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";


/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;

--
-- Database: `jdbc_tutorial`
--
CREATE DATABASE IF NOT EXISTS `jdbc_tutorial` DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci;
USE `jdbc_tutorial`;

DELIMITER $$
--
-- Functions
--
DROP FUNCTION IF EXISTS `getAge`$$
CREATE DEFINER=`root`@`localhost` FUNCTION `getAge` (`in_dob` DATE) RETURNS INT(11) NO SQL
BEGIN
DECLARE l_age INT;
   IF DATE_FORMAT(NOW(),'00-%m-%d') >= DATE_FORMAT(in_dob,'00-%m-%d') THEN
      -- This person has had a birthday this year
      SET l_age=DATE_FORMAT(NOW(),'%Y')-DATE_FORMAT(in_dob,'%Y');
   ELSE
      -- Yet to have a birthday this year
      SET l_age=DATE_FORMAT(NOW(),'%Y')-DATE_FORMAT(in_dob,'%Y')-1;
   END IF;
      RETURN(l_age);
END$$

DELIMITER ;

-- --------------------------------------------------------

--
-- Table structure for table `beatles`
--

DROP TABLE IF EXISTS `beatles`;
CREATE TABLE IF NOT EXISTS `beatles` (
  `id` int(11) NOT NULL,
  `first_name` varchar(255) DEFAULT NULL,
  `last_name` varchar(255) DEFAULT NULL,
  `date_of_birth` date DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

--
-- Truncate table before insert `beatles`
--

TRUNCATE TABLE `beatles`;
--
-- Dumping data for table `beatles`
--

INSERT INTO `beatles` (`id`, `first_name`, `last_name`, `date_of_birth`) VALUES(100, 'John', 'Lennon', '1940-10-09');
INSERT INTO `beatles` (`id`, `first_name`, `last_name`, `date_of_birth`) VALUES(101, 'Paul', 'McCartney', '1942-06-18');
INSERT INTO `beatles` (`id`, `first_name`, `last_name`, `date_of_birth`) VALUES(102, 'George', 'Harrison', '1943-02-25');
INSERT INTO `beatles` (`id`, `first_name`, `last_name`, `date_of_birth`) VALUES(103, 'Ringo', 'Starr', '1940-07-07');

/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;

build.gradle

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'application'

mainClassName = 'com.oracle.jdbc.QueryApp'

repositories {
    maven  {
        url "http://repo1.maven.org/maven2"
    }
}

jar {
    baseName = 'jdbc-tutorial'
    version =  '1.0.0'
}

sourceCompatibility = 1.7
targetCompatibility = 1.7

dependencies {
    compile 'mysql:mysql-connector-java:5.1.16'
    compile 'com.google.guava:guava:18.0'
    compile 'com.google.code.gson:gson:1.7.2'
}

task wrapper(type: Wrapper) {
    gradleVersion = '2.9'
}

ผล

การเลือกพื้นฐาน

[
    {
        "firstName": "John",
        "lastName": "Lennon",
        "dateOfBirth": "1940-10-09",
        "id": 100
    },
    {
        "firstName": "Paul",
        "lastName": "McCartney",
        "dateOfBirth": "1942-06-18",
        "id": 101
    },
    {
        "firstName": "George",
        "lastName": "Harrison",
        "dateOfBirth": "1943-02-25",
        "id": 102
    },
    {
        "firstName": "Ringo",
        "lastName": "Starr",
        "dateOfBirth": "1940-07-07",
        "id": 103
    }
]

เลือกระดับกลาง

[
    {
        "firstName": "John",
        "lastName": "Lennon",
        "age": 75
    },
    {
        "firstName": "Paul",
        "lastName": "McCartney",
        "age": 73
    },
    {
        "firstName": "George",
        "lastName": "Harrison",
        "age": 72
    },
    {
        "firstName": "Ringo",
        "lastName": "Starr",
        "age": 75
    }
]

3

ชื่อคอลัมน์ที่สร้างไว้ล่วงหน้าครั้งแรกใช้ครั้งที่สองrs.getString(i)แทนrs.getString(column_name)แทน

ต่อไปนี้คือการนำไปใช้:

    /*
     * Convert ResultSet to a common JSON Object array
     * Result is like: [{"ID":"1","NAME":"Tom","AGE":"24"}, {"ID":"2","NAME":"Bob","AGE":"26"}, ...]
     */
    public static List<JSONObject> getFormattedResult(ResultSet rs) {
        List<JSONObject> resList = new ArrayList<JSONObject>();
        try {
            // get column names
            ResultSetMetaData rsMeta = rs.getMetaData();
            int columnCnt = rsMeta.getColumnCount();
            List<String> columnNames = new ArrayList<String>();
            for(int i=1;i<=columnCnt;i++) {
                columnNames.add(rsMeta.getColumnName(i).toUpperCase());
            }

            while(rs.next()) { // convert each object to an human readable JSON object
                JSONObject obj = new JSONObject();
                for(int i=1;i<=columnCnt;i++) {
                    String key = columnNames.get(i - 1);
                    String value = rs.getString(i);
                    obj.put(key, value);
                }
                resList.add(obj);
            }
        } catch(Exception e) {
            e.printStackTrace();
        } finally {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return resList;
    }

ฉันจะเข้าถึงและใช้ออบเจ็กต์ได้อย่างไร .... บอกว่าฉันต้องการพิมพ์คอลัมน์ Name ทั้งหมด .. และอ็อบเจ็กต์นั้นสามารถใช้ได้อย่างง่ายดายสำหรับการดำเนินการ CRUD หรือไม่?
พระธาเมศวร

@Prathameshdhanawade วิธีนี้เป็นการปกปิด JDBC ResultSet ไปยังอาร์เรย์ JSON นักพัฒนามักจะไม่ใช้ JDBC ResultSet แบบดิบพวกเขามักจะแปลงเป็นรายการวัตถุ Java เช่นออบเจ็กต์ JSON คุณจะเห็นค่าที่ส่งคืนคืออาร์เรย์ของออบเจ็กต์ JSON คุณได้อย่างง่ายดายสามารถเข้าถึงวัตถุหนึ่งผ่านแล้วคุณมีอิสระในการจัดการกับวัตถุJSONObject json = resList.get(i); JSON json
coderz

ที่จริงแล้วฉันต้องการวัตถุเพื่อเตรียมมุมมองกราฟิก ดังนั้นฉันแค่อยากรู้อยากเห็นฉันสามารถจัดการกับวัตถุได้ Thnx.
Prathamesh dhanawade

คุณช่วยอธิบาย "มุมมองกราฟิก" ได้ไหม หรือยกตัวอย่าง?
coderz

ฉันกำลังพยายามแสดงค่าคอลัมน์เป็น: JSONObject obj = jsonList.get (1); System.out.println (obj.getString ("name") + "\ t" + obj.getString ("บริษัท ")); แต่ได้รับข้อผิดพลาดเป็น "org.json.JSONException: JSONObject [" name "] ไม่พบ"
Prathamesh dhanawade

2

หากใครวางแผนจะใช้การใช้งานนี้คุณอาจต้องการตรวจสอบสิ่งนี้ และสิ่งนี้

นี่คือรหัสแปลงรุ่นของฉัน:

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

        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.getLong(column_name));
            } else if (rsmd.getColumnType(i) == java.sql.Types.REAL) {
                obj.put(column_name, rs.getFloat(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.getDouble(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.CHAR) {
                obj.put(column_name, rs.getString(column_name));
            } else if (rsmd.getColumnType(i) == java.sql.Types.NCHAR) {
                obj.put(column_name, rs.getNString(column_name));
            } else if (rsmd.getColumnType(i) == java.sql.Types.LONGNVARCHAR) {
                obj.put(column_name, rs.getNString(column_name));
            } else if (rsmd.getColumnType(i) == java.sql.Types.LONGVARCHAR) {
                obj.put(column_name, rs.getString(column_name));
            } else if (rsmd.getColumnType(i) == java.sql.Types.TINYINT) {
                obj.put(column_name, rs.getByte(column_name));
            } else if (rsmd.getColumnType(i) == java.sql.Types.SMALLINT) {
                obj.put(column_name, rs.getShort(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.TIME) {
                obj.put(column_name, rs.getTime(column_name));
            } else if (rsmd.getColumnType(i) == java.sql.Types.TIMESTAMP) {
                obj.put(column_name, rs.getTimestamp(column_name));
            } else if (rsmd.getColumnType(i) == java.sql.Types.BINARY) {
                obj.put(column_name, rs.getBytes(column_name));
            } else if (rsmd.getColumnType(i) == java.sql.Types.VARBINARY) {
                obj.put(column_name, rs.getBytes(column_name));
            } else if (rsmd.getColumnType(i) == java.sql.Types.LONGVARBINARY) {
                obj.put(column_name, rs.getBinaryStream(column_name));
            } else if (rsmd.getColumnType(i) == java.sql.Types.BIT) {
                obj.put(column_name, rs.getBoolean(column_name));
            } else if (rsmd.getColumnType(i) == java.sql.Types.CLOB) {
                obj.put(column_name, rs.getClob(column_name));
            } else if (rsmd.getColumnType(i) == java.sql.Types.NUMERIC) {
                obj.put(column_name, rs.getBigDecimal(column_name));
            } else if (rsmd.getColumnType(i) == java.sql.Types.DECIMAL) {
                obj.put(column_name, rs.getBigDecimal(column_name));
            } else if (rsmd.getColumnType(i) == java.sql.Types.DATALINK) {
                obj.put(column_name, rs.getURL(column_name));
            } else if (rsmd.getColumnType(i) == java.sql.Types.REF) {
                obj.put(column_name, rs.getRef(column_name));
            } else if (rsmd.getColumnType(i) == java.sql.Types.STRUCT) {
                obj.put(column_name, rs.getObject(column_name)); // must be a custom mapping consists of a class that implements the interface SQLData and an entry in a java.util.Map object.
            } else if (rsmd.getColumnType(i) == java.sql.Types.DISTINCT) {
                obj.put(column_name, rs.getObject(column_name)); // must be a custom mapping consists of a class that implements the interface SQLData and an entry in a java.util.Map object.
            } else if (rsmd.getColumnType(i) == java.sql.Types.JAVA_OBJECT) {
                obj.put(column_name, rs.getObject(column_name));
            } else {
                obj.put(column_name, rs.getString(i));
            }
        }

        json.put(obj);
    }

    return json;
}
}

2

เช่นเดียวกับการแจ้งเตือนการวนซ้ำ if / then จะมีประสิทธิภาพมากกว่าสวิตช์สำหรับ enums หากคุณมีการสลับกับจำนวนเต็ม raw enum แสดงว่ามีประสิทธิภาพมากกว่า แต่เมื่อเทียบกับตัวแปรถ้า / แล้วจะมีประสิทธิภาพมากกว่าอย่างน้อยสำหรับ Java 5, 6 และ 7

กล่าวคือด้วยเหตุผลบางประการ (หลังจากการทดสอบประสิทธิภาพบางอย่าง)

if (ordinalValue == 1) {
   ...
} else (ordinalValue == 2 {
   ... 
}

เร็วกว่า

switch( myEnum.ordinal() ) {
    case 1:
       ...
       break;
    case 2:
       ...
       break;
}

ฉันเห็นว่ามีคนไม่กี่คนที่สงสัยฉันดังนั้นฉันจะโพสต์รหัสที่นี่เพื่อให้คุณสามารถเรียกใช้ตัวเองเพื่อดูความแตกต่างพร้อมกับผลลัพธ์ที่ฉันได้รับจาก Java 7 ผลลัพธ์ของโค้ดต่อไปนี้ที่มีค่า enum 10 ค่ามีดังนี้ สังเกตว่าคีย์ในที่นี้คือ if / แล้วโดยใช้ค่าจำนวนเต็มเปรียบเทียบกับค่าคงที่ลำดับของ enum เทียบกับสวิตช์ที่มีค่าลำดับของ enum เทียบกับค่า int ลำดับดิบเทียบกับสวิตช์ที่มี enum เทียบกับชื่อ enum แต่ละชื่อ if / then ที่มีค่าจำนวนเต็มเอาชนะสวิตช์อื่น ๆ ทั้งสองแม้ว่าสวิตช์สุดท้ายจะเร็วกว่าสวิตช์แรกเล็กน้อย แต่ก็ไม่เร็วกว่า if / else

ถ้า / else ใช้เวลา 23 ms
Switch ใช้เวลา 45 ms
Switch 2 ใช้เวลา 30 ms
ทั้งหมดที่ตรงกัน: 3000000

package testing;

import java.util.Random;

enum TestEnum {
    FIRST,
    SECOND,
    THIRD,
    FOURTH,
    FIFTH,
    SIXTH,
    SEVENTH,
    EIGHTH,
    NINTH,
    TENTH
}

public class SwitchTest {
    private static int LOOP = 1000000;
    private static Random r = new Random();
    private static int SIZE = TestEnum.values().length;

    public static void main(String[] args) {
        long time = System.currentTimeMillis();
        int matches = 0;
        for (int i = 0; i < LOOP; i++) {
            int j = r.nextInt(SIZE);
            if (j == TestEnum.FIRST.ordinal()) {
                matches++;
            } else if (j == TestEnum.SECOND.ordinal()) {
                matches++;
            } else if (j == TestEnum.THIRD.ordinal()) {
                matches++;
            } else if (j == TestEnum.FOURTH.ordinal()) {
                matches++;
            } else if (j == TestEnum.FIFTH.ordinal()) {
                matches++;
            } else if (j == TestEnum.SIXTH.ordinal()) {
                matches++;
            } else if (j == TestEnum.SEVENTH.ordinal()) {
                matches++;
            } else if (j == TestEnum.EIGHTH.ordinal()) {
                matches++;
            } else if (j == TestEnum.NINTH.ordinal()) {
                matches++;
            } else {
                matches++;
            }
        }
        System.out.println("If / else took "+(System.currentTimeMillis() - time)+" ms");
        time = System.currentTimeMillis();
        for (int i = 0; i < LOOP; i++) {
            TestEnum te = TestEnum.values()[r.nextInt(SIZE)];
            switch (te.ordinal()) {
                case 0:
                    matches++;
                    break;
                case 1:
                    matches++;
                    break;
                case 2:
                    matches++;
                    break;
                case 3:
                    matches++;
                    break;
                case 4:
                    matches++;
                    break;
                case 5:
                    matches++;
                    break;
                case 6:
                    matches++;
                    break;
                case 7:
                    matches++;
                    break;
                case 8:
                    matches++;
                    break;
                case 9:
                    matches++;
                    break;
                default:
                    matches++;
                    break;
            }
        }
        System.out.println("Switch took "+(System.currentTimeMillis() - time)+" ms");
        time = System.currentTimeMillis();
        for (int i = 0; i < LOOP; i++) {
            TestEnum te = TestEnum.values()[r.nextInt(SIZE)];
            switch (te) {
                case FIRST:
                    matches++;
                    break;
                case SECOND:
                    matches++;
                    break;
                case THIRD:
                    matches++;
                    break;
                case FOURTH:
                    matches++;
                    break;
                case FIFTH:
                    matches++;
                    break;
                case SIXTH:
                    matches++;
                    break;
                case SEVENTH:
                    matches++;
                    break;
                case EIGHTH:
                    matches++;
                    break;
                case NINTH:
                    matches++;
                    break;
                default:
                    matches++;
                    break;
            }
        }
        System.out.println("Switch 2 took "+(System.currentTimeMillis() - time)+" ms");     
        System.out.println("Total matches: "+matches);
    }
}

โอเค แต่ .. ความจริงในทางปฏิบัติก็คือความแตกต่างระหว่างทางเลือกในการเข้ารหัสเหล่านี้สำหรับกรณีการใช้งานจริงนั้นมีน้อยมากจนในแอปพลิเคชันจริงความแตกต่างของประสิทธิภาพในหมู่พวกเขามักจะน้อยมาก ทำให้รหัสของคุณถูกต้องก่อนแล้ว (เท่านั้น) ทำให้เร็ว (ถ้าจำเป็นต้องเร็วกว่า)
scottb

เห็นด้วย แต่คำถามหลักเกี่ยวกับวิธีที่เร็วและมีประสิทธิภาพที่สุด มีหลายสไตล์ที่ทำให้โค้ดอ่านยากหรือดูแลรักษาได้ยาก แต่มีประสิทธิภาพมากกว่าแม้ว่าโดยทั่วไปแล้วสิ่งเหล่านี้จะได้รับการแก้ไขโดยการปรับแต่งคอมไพลเลอร์ในบางจุดในอนาคต ตัวอย่างหนึ่งของสิ่งนี้คือการใช้intern()สำหรับสตริงซึ่งส่วนใหญ่ไม่จำเป็นอีกต่อไปใน Java เวอร์ชันที่ทันสมัยที่สุด
Marcus

เห็นด้วย แต่ if-then-else และ switch-case block นั้นเป็นวิธีแก้ปัญหาที่ไม่ดีสำหรับปัญหาด้านการบำรุงรักษาความทนทานและความสามารถในการอ่านไม่ว่าในกรณีใด ๆ สำหรับ enums ที่คุณเป็นเจ้าของ (หรือมีรหัสที่คุณสามารถแก้ไขได้) แนวทางปฏิบัติที่ดีที่สุดมักจะใช้วิธีการที่เฉพาะเจาะจงคงที่ในประเภท enum ที่หลากหลายโดยส่วนใหญ่แล้วการเปิด enum ควรดูด้วยความรอบคอบเนื่องจากมีคุณสมบัติที่ดีกว่า วิธีแก้ปัญหาที่นั่น
scottb

1

สำหรับทุกคนที่เลือกใช้โซลูชัน if-else mesh โปรดใช้:

String columnName = metadata.getColumnName(
String displayName = metadata.getColumnLabel(i);
switch (metadata.getColumnType(i)) {
case Types.ARRAY:
    obj.put(displayName, resultSet.getArray(columnName));
    break;
...

เนื่องจากในกรณีของนามแฝงในข้อความค้นหาของคุณชื่อคอลัมน์และป้ายชื่อคอลัมน์จึงเป็นสองสิ่งที่แตกต่างกัน ตัวอย่างเช่นหากคุณดำเนินการ:

select col1, col2 as my_alias from table

คุณจะได้รับ

[
    { "col1": 1, "col2": 2 }, 
    { "col1": 1, "col2": 2 }
]

ค่อนข้างมากกว่า:

[
    { "col1": 1, "my_alias": 2 }, 
    { "col1": 1, "my_alias": 2 }
]

0
package com.idal.cib;

import java.io.FileWriter;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;

public class DBJsonConverter {

    static ArrayList<String> data = new ArrayList<String>();
    static Connection conn = null;
    static PreparedStatement ps = null;
    static ResultSet rs = null;
    static String path = "";
    static String driver="";
    static String url="";
    static String username="";
    static String password="";
    static String query="";

    @SuppressWarnings({ "unchecked" })
    public static void dataLoad(String path) {
        JSONObject obj1 = new JSONObject();
        JSONArray jsonArray = new JSONArray();
        conn = DatabaseConnector.getDbConnection(driver, url, username,
                password);
        try {
            ps = conn.prepareStatement(query);
            rs = ps.executeQuery();
            ArrayList<String> columnNames = new ArrayList<String>();
            if (rs != null) {
                ResultSetMetaData columns = rs.getMetaData();
                int i = 0;
                while (i < columns.getColumnCount()) {
                    i++;
                    columnNames.add(columns.getColumnName(i));
                }
                while (rs.next()) {
                    JSONObject obj = new JSONObject();
                    for (i = 0; i < columnNames.size(); i++) {
                        data.add(rs.getString(columnNames.get(i)));
                        {
                            for (int j = 0; j < data.size(); j++) {
                                if (data.get(j) != null) {
                                    obj.put(columnNames.get(i), data.get(j));
                                }else {
                                    obj.put(columnNames.get(i), "");
                                }
                            }
                        }
                    }

                    jsonArray.add(obj);
                    obj1.put("header", jsonArray);
                    FileWriter file = new FileWriter(path);
                    file.write(obj1.toJSONString());
                    file.flush();
                    file.close();
                }
                ps.close();
            } else {
                JSONObject obj2 = new JSONObject();
                obj2.put(null, null);
                jsonArray.add(obj2);
                obj1.put("header", jsonArray);
            }
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            if (conn != null) {
                try {
                    conn.close();
                    rs.close();
                    ps.close();
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    }

    @SuppressWarnings("static-access")
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        driver = "oracle.jdbc.driver.OracleDriver";
        url = "jdbc:oracle:thin:@localhost:1521:database";
        username = "user";
        password = "password";
        path = "path of file";
        query = "select * from temp_employee";

        DatabaseConnector dc = new DatabaseConnector();
        dc.getDbConnection(driver,url,username,password);
        DBJsonConverter formatter = new DBJsonConverter();
        formatter.dataLoad(path);

    }

}




package com.idal.cib;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class DatabaseConnector {

    static Connection conn1 = null;

    public static Connection getDbConnection(String driver, String url,
            String username, String password) {
        // TODO Auto-generated constructor stub
        try {

            Class.forName(driver);

            conn1 = DriverManager.getConnection(url, username, password);
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return conn1;
    }

}

กรุณาเพิ่มคำอธิบายในคำตอบของคุณ
Sahil Mittal

0
public static JSONArray GetJSONDataFromResultSet(ResultSet rs) throws SQLException {
    ResultSetMetaData metaData = rs.getMetaData();
    int count = metaData.getColumnCount();
    String[] columnName = new String[count];
    JSONArray jsonArray = new JSONArray();
    while(rs.next()) {
        JSONObject jsonObject = new JSONObject();
        for (int i = 1; i <= count; i++){
               columnName[i-1] = metaData.getColumnLabel(i);
               jsonObject.put(columnName[i-1], rs.getObject(i));
        }
        jsonArray.put(jsonObject);
    }
    return jsonArray;
}

-1

ในทางกลับกันที่นี่ฉันใช้ ArrayList และ Map ดังนั้นจึงไม่เรียกวัตถุ json ทีละแถว แต่หลังจากการทำซ้ำผลลัพธ์เสร็จสิ้น:

 List<Map<String, String>> list = new ArrayList<Map<String, String>>();

  ResultSetMetaData rsMetaData = rs.getMetaData();  


      while(rs.next()){

              Map map = new HashMap();
              for (int i = 1; i <= rsMetaData.getColumnCount(); i++) {
                 String key = rsMetaData.getColumnName(i);

                  String value = null;

               if (rsmd.getColumnType(i) == java.sql.Types.VARCHAR) {
                           value = rs.getString(key);
               } else if(rsmd.getColumnType(i)==java.sql.Types.BIGINT)                         
                             value = rs.getLong(key);
               }                  


                    map.put(key, value);
              }
              list.add(map);


    }


     json.put(list);    
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.