Oracle
 sql >> डेटाबेस >  >> RDS >> Oracle

एक संग्रहीत प्रक्रिया द्वारा लौटाए गए एक स्ट्रक्ट से एक सरणी पढ़ें

ऐसे ऑब्जेक्ट बनाएं जो java.sql.SQLData implement को लागू करें . इस परिदृश्य में, TEnclosure create बनाएं और TAnimal कक्षाएं, जो दोनों लागू करते हैं SQLData

सिर्फ FYI करें, नए Oracle JDBC संस्करणों में, oracle जैसे प्रकार .sql.ARRAY java.sql . के पक्ष में बहिष्कृत हैं प्रकार। हालांकि मुझे यकीन नहीं है कि केवल java.sql का उपयोग करके एक सरणी (नीचे वर्णित) कैसे लिखना है एपीआई।

जब आप readSQL() लागू करते हैं आप क्रम में फ़ील्ड पढ़ते हैं। आपको एक java.sql.Array प्राप्त होता है sqlInput.readArray() . के साथ . तो TEnclosure.readSQL() कुछ इस तरह दिखेगा।

@Override
public void readSQL(SQLInput sqlInput, String s) throws SQLException {
    id = sqlInput.readBigDecimal();
    name = sqlInput.readString();
    Array animals = sqlInput.readArray();
    // what to do here...
}

नोट:readInt() भी मौजूद है, लेकिन Oracle JDBC हमेशा BigDecimal provide प्रदान करता प्रतीत होता है NUMBER . के लिए

आप देखेंगे कि कुछ एपीआई जैसे java.sql.Array ऐसे तरीके हैं जो एक प्रकार का नक्शा लेते हैं Map<String, Class<?>> यह SQLData implementing को लागू करने वाले संबंधित जावा वर्ग के लिए Oracle प्रकार के नामों का मानचित्रण है (ORAData भी काम कर सकता है?)

अगर आप सिर्फ Array.getArray() call पर कॉल करते हैं , आपको Struct मिलेगा ऑब्जेक्ट्स जब तक JDBC ड्राइवर Connection.setTypeMap(typeMap) के माध्यम से आपके टाइप मैपिंग के बारे में नहीं जानता है। . हालांकि, कनेक्शन पर टाइपमैप सेट करना मेरे लिए काम नहीं करता था, इसलिए मैं getArray(typeMap) का उपयोग करता हूं

अपना Map<String, Class<?>> typeMap बनाएं कहीं और अपने प्रकार के लिए प्रविष्टियां जोड़ें:

typeMap.put("T_ENCLOSURE", TEnclosure.class);
typeMap.put("T_ANIMAL", TAnimal.class);

एक SQLData.readSQL() . के भीतर कार्यान्वयन, कॉल करें sqlInput.readArray().getArray(typeMap) , जो Object[] returns लौटाता है जहां Object प्रविष्टियाँ या प्रकार TAnimal

बेशक एक List<TAnimal> . में कनवर्ट करने के लिए कोड थकाऊ हो जाता है, इसलिए बस इस उपयोगिता फ़ंक्शन का उपयोग करें और इसे अपनी आवश्यकताओं के लिए समायोजित करें जहां तक ​​​​शून्य बनाम खाली सूची नीति:

/**
 * Constructs a list from the given SQL Array
 * Note: this needs to be static because it's called from SQLData classes.
 *
 * @param <T> SQLData implementing class
 * @param array Array containing objects of type T
 * @param typeClass Class reference used to cast T type
 * @return List<T> (empty if array=null)
 * @throws SQLException
 */
public static <T> List<T> listFromArray(Array array, Class<T> typeClass) throws SQLException {
    if (array == null) {
        return Collections.emptyList();
    }
    // Java does not allow casting Object[] to T[]
    final Object[] objectArray = (Object[]) array.getArray(getTypeMap());
    List<T> list = new ArrayList<>(objectArray.length);
    for (Object o : objectArray) {
        list.add(typeClass.cast(o));
    }
    return list;
}

लेखन सारणियां

यह पता लगाना कि कैसे एक सरणी लिखना निराशाजनक था, Oracle API को एक सरणी बनाने के लिए एक कनेक्शन की आवश्यकता होती है, लेकिन आपके पास writeSQL(SQLOutput sqlOutput) के संदर्भ में एक स्पष्ट कनेक्शन नहीं है। . सौभाग्य से, यह ब्लॉग OracleConnection . प्राप्त करने के लिए एक ट्रिक/हैक है , जिसका मैंने यहां उपयोग किया है।

जब आप createOracleArray() . के साथ एक ऐरे बनाते हैं आप सूची प्रकार निर्दिष्ट करें (T_ARRAY_ANIMALS ) प्रकार के नाम के लिए, एकवचन वस्तु प्रकार नहीं।

यहाँ सरणियाँ लिखने के लिए एक सामान्य कार्य है। आपके मामले में, listType "T_ARRAY_ANIMALS" . होगा और आप List<TAnimal> . में पास होंगे

/**
 * Write the list out as an Array
 *
 * @param sqlOutput SQLOutput to write array to
 * @param listType array type name (table of type)
 * @param list List of objects to write as an array
 * @param <T> Class implementing SQLData that corresponds to the type listType is a list of.
 * @throws SQLException
 * @throws ClassCastException if SQLOutput is not an OracleSQLOutput
 */
public static <T> void writeArrayFromList(SQLOutput sqlOutput, String listType, @Nullable List<T> list) throws SQLException {
    final OracleSQLOutput out = (OracleSQLOutput) sqlOutput;
    OracleConnection conn = (OracleConnection) out.getSTRUCT().getJavaSqlConnection();
    conn.setTypeMap(getTypeMap());  // not needed?
    if (list == null) {
        list = Collections.emptyList();
    }
    final Array array = conn.createOracleArray(listType, list.toArray());
    out.writeArray(array);
}

नोट:

  • एक समय मैंने सोचा था कि setTypeMap आवश्यक था, लेकिन अब जब मैं उस लाइन को हटाता हूं तो मेरा कोड अभी भी काम करता है, इसलिए मुझे यकीन नहीं है कि यह आवश्यक है या नहीं।
  • मैं निश्चित नहीं हूं कि आपको शून्य या एक खाली सरणी लिखनी चाहिए, लेकिन मुझे लगता है कि खाली सरणी अधिक सही है।

Oracle प्रकारों पर युक्तियाँ

  • Oracle सब कुछ अपरकेस करता है, इसलिए सभी प्रकार के नाम अपरकेस होने चाहिए।
  • आपको SCHEMA.TYPE_NAME निर्दिष्ट करने की आवश्यकता हो सकती है यदि प्रकार आपके डिफ़ॉल्ट स्कीमा में नहीं है।
  • grant execute याद रखें प्रकारों पर यदि आप जिस उपयोगकर्ता से जुड़ रहे हैं वह स्वामी नहीं है।
    यदि आपने पैकेज पर निष्पादन किया है, लेकिन प्रकार नहीं, getArray() जब यह मेटाडेटा टाइप करने की कोशिश करता है तो एक अपवाद फेंक देगा।

वसंत

वसंत . का उपयोग करने वाले डेवलपर के लिए , आप स्प्रिंग डेटा JDBC एक्सटेंशन देखना चाह सकते हैं , जो SqlArrayValue . प्रदान करता है और SqlReturnArray , जो एक SimpleJdbcCall . बनाने के लिए उपयोगी हैं एक ऐसी प्रक्रिया के लिए जो एक सरणी को तर्क के रूप में लेती है या एक सरणी लौटाती है।

अध्याय 7.2.1 एक IN पैरामीटर के लिए SqlArrayValue का उपयोग करके ARRAY मान सेट करना सरणी पैरामीटर के साथ प्रक्रियाओं को कॉल करने का तरीका बताता है।



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. sql - ORA-00937:एकल-समूह समूह फ़ंक्शन नहीं

  2. मैं Oracle में किसी अनुक्रमणिका और तालिका स्वामी के बारे में जानकारी कैसे प्राप्त करूं?

  3. पर्ल डीबीडी ::ओरेकल मॉड्यूल स्थापना

  4. कैसे जांचें कि ओरेकल में सभी फ़ील्ड अद्वितीय हैं या नहीं?

  5. वेब सेवा का उपभोग करना और Oracle डेटाबेस तालिका में Node.js का उपयोग करके CLOB सम्मिलित करना