|
| 1 | +/* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.*/ |
| 2 | + |
| 3 | +/* |
| 4 | + DESCRIPTION |
| 5 | + |
| 6 | + REF CURSOR as INPUT parameter sample. |
| 7 | + This capability was added in the JDBC thin driver in 18c. |
| 8 | + To run the sample, you must enter the DB user's password from the |
| 9 | + console, and optionally specify the DB user and/or connect URL on |
| 10 | + the command-line. You can also modify these values in this file |
| 11 | + and recompile the code. |
| 12 | + java RefCursorInSample -l <url> -u <user> |
| 13 | + */ |
| 14 | + |
| 15 | +import java.io.BufferedReader; |
| 16 | +import java.io.InputStreamReader; |
| 17 | +import java.sql.CallableStatement; |
| 18 | +import java.sql.Connection; |
| 19 | +import java.sql.ResultSet; |
| 20 | +import java.sql.SQLException; |
| 21 | +import java.sql.Statement; |
| 22 | + |
| 23 | +import oracle.jdbc.OracleTypes; |
| 24 | +import oracle.jdbc.pool.OracleDataSource; |
| 25 | +import oracle.jdbc.OracleCallableStatement; |
| 26 | + |
| 27 | +public class RefCursorInSample { |
| 28 | + |
| 29 | + final static String DEFAULT_URL = "jdbc:oracle:thin:@//myhost:myport/myservice"; |
| 30 | + final static String DEFAULT_USER = "myuser"; |
| 31 | + final static String DEFAULT_PASSWORD = "mypassword"; |
| 32 | + |
| 33 | + // You must provide non-default values for all 3 parameters to execute the program |
| 34 | + static String url = DEFAULT_URL; |
| 35 | + static String user = DEFAULT_USER; |
| 36 | + static String password = DEFAULT_PASSWORD; |
| 37 | + |
| 38 | + // Connection object for REF CURSOR as INPUT parameter. |
| 39 | + // The sample uses only one connection for all REF CURSOR |
| 40 | + // operations in this demo program. |
| 41 | + private Connection conn; |
| 42 | + |
| 43 | + // Package name used in this sample |
| 44 | + private final String PACKAGE_NAME = "REF_CURSOR_IN_JDBC_SAMPLE"; |
| 45 | + |
| 46 | + // Function names used in this sample |
| 47 | + private final String FUNCTION_NAME1 = "GET_EMP_CURSOR"; |
| 48 | + private final String FUNCTION_NAME2 = "NAVIGATE_EMP_CURSOR"; |
| 49 | + |
| 50 | + |
| 51 | + /** |
| 52 | + * Entry point of the sample. |
| 53 | + * |
| 54 | + * @param args |
| 55 | + * Command line arguments. Supported command line options: -l <url> |
| 56 | + * -u <user> |
| 57 | + * @throws Exception |
| 58 | + */ |
| 59 | + public static void main(String args[]) throws Exception { |
| 60 | + RefCursorInSample refCursorSample = new RefCursorInSample(); |
| 61 | + |
| 62 | + getRealUserPasswordUrl(args); |
| 63 | + |
| 64 | + // Get a connection and initialize the schema. |
| 65 | + refCursorSample.setup(); |
| 66 | + |
| 67 | + // Shows REF CURSOR IN with setCursor() call |
| 68 | + refCursorSample.setCursorSample(); |
| 69 | + |
| 70 | + // Drop table and disconnect from the database. |
| 71 | + refCursorSample.cleanup(); |
| 72 | + } |
| 73 | + |
| 74 | + // Gets connection to the database and create a stored procedure. |
| 75 | + void setup() throws SQLException { |
| 76 | + conn = getConnection(); |
| 77 | + createFunctions(); |
| 78 | + } |
| 79 | + |
| 80 | + // Drop the stored procedure and disconnect from the database |
| 81 | + void cleanup() throws SQLException { |
| 82 | + if (conn != null) { |
| 83 | + dropFunctions(); |
| 84 | + conn.close(); |
| 85 | + conn = null; |
| 86 | + } |
| 87 | + } |
| 88 | + |
| 89 | + // Shows how to use REF CURSOR IN with setCursor() call |
| 90 | + void setCursorSample() throws SQLException { |
| 91 | + |
| 92 | + show("======== setCursor Sample ========"); |
| 93 | + |
| 94 | + // Prepare a PL/SQL call to get a REF CURSOR as an output |
| 95 | + try ( CallableStatement call1 = |
| 96 | + conn.prepareCall ("{ ? = call " + PACKAGE_NAME + "." + FUNCTION_NAME1 + "() }")) { |
| 97 | + call1.registerOutParameter (1, OracleTypes.CURSOR); |
| 98 | + call1.execute (); |
| 99 | + try (ResultSet rset = (ResultSet)call1.getObject (1) ) { |
| 100 | + |
| 101 | + // Dump the first row from the cursor |
| 102 | + show("Fetch first row of a ref cursor in Java:"); |
| 103 | + if(rset.next ()) |
| 104 | + show(rset.getString ("EMPNO") + " " |
| 105 | + + rset.getString ("ENAME")); |
| 106 | + |
| 107 | + // Prepare a PL/SQL call to set a REF CURSOR as an input |
| 108 | + try ( CallableStatement call2 = |
| 109 | + conn.prepareCall ("{ ? = call " + PACKAGE_NAME + "." + FUNCTION_NAME2 + "(?) }")) { |
| 110 | + |
| 111 | + call2.registerOutParameter (1, OracleTypes.INTEGER); |
| 112 | + ((OracleCallableStatement)call2).setCursor(2, rset); |
| 113 | + call2.execute (); |
| 114 | + |
| 115 | + int empno = call2.getInt(1); |
| 116 | + |
| 117 | + show("Fetch second row of the ref cursor in PL/SQL: empno=" + empno); |
| 118 | + |
| 119 | + // Dump the rest of the cursor |
| 120 | + show("Fetch rest of the ref cursor rows in Java:"); |
| 121 | + while (rset.next ()) |
| 122 | + show(rset.getString ("EMPNO") + " " |
| 123 | + + rset.getString ("ENAME")); |
| 124 | + |
| 125 | + } // call2 |
| 126 | + } // rset |
| 127 | + } // call1 |
| 128 | + } |
| 129 | + |
| 130 | + // ==============================Utility Methods============================== |
| 131 | + |
| 132 | + private void createFunctions() throws SQLException { |
| 133 | + try (Statement stmt = conn.createStatement()) { |
| 134 | + String sql = "CREATE OR REPLACE PACKAGE " + PACKAGE_NAME + " AS " + |
| 135 | + " TYPE mycursortype IS REF CURSOR RETURN EMP%ROWTYPE; " + |
| 136 | + " FUNCTION " + FUNCTION_NAME1 + " RETURN mycursortype; " + |
| 137 | + " FUNCTION " + FUNCTION_NAME2 + " (mycursor mycursortype) RETURN NUMBER; " + |
| 138 | + "END " + PACKAGE_NAME + ";"; |
| 139 | + |
| 140 | + stmt.execute (sql); |
| 141 | + |
| 142 | + sql = "CREATE OR REPLACE PACKAGE BODY " + PACKAGE_NAME + " AS " + |
| 143 | + " FUNCTION " + FUNCTION_NAME1 + " RETURN mycursortype IS " + |
| 144 | + " rc mycursortype; " + |
| 145 | + " BEGIN " + |
| 146 | + " OPEN rc FOR SELECT * FROM emp ORDER BY empno;" + |
| 147 | + " RETURN rc; " + |
| 148 | + " END " + FUNCTION_NAME1 + "; " + |
| 149 | + " " + |
| 150 | + " FUNCTION " + FUNCTION_NAME2 + " (mycursor mycursortype) RETURN NUMBER IS " + |
| 151 | + " rc NUMBER; " + |
| 152 | + " myrecord EMP%ROWTYPE;" + |
| 153 | + " BEGIN " + |
| 154 | + " FETCH mycursor INTO myrecord;" + |
| 155 | + " rc := myrecord.EMPNO;" + |
| 156 | + " RETURN rc; " + |
| 157 | + " END " + FUNCTION_NAME2 + "; " + |
| 158 | + " " + |
| 159 | + "END " + PACKAGE_NAME + ";"; |
| 160 | + |
| 161 | + stmt.execute (sql); |
| 162 | + } |
| 163 | + } |
| 164 | + |
| 165 | + private void dropFunctions() throws SQLException { |
| 166 | + try (Statement stmt = conn.createStatement()) { |
| 167 | + stmt.execute ("DROP PACKAGE " + PACKAGE_NAME); |
| 168 | + } |
| 169 | + } |
| 170 | + |
| 171 | + private Connection getConnection() throws SQLException { |
| 172 | + // Create an OracleDataSource instance and set properties |
| 173 | + OracleDataSource ods = new OracleDataSource(); |
| 174 | + ods.setUser(user); |
| 175 | + ods.setPassword(password); |
| 176 | + ods.setURL(url); |
| 177 | + |
| 178 | + return ods.getConnection(); |
| 179 | + } |
| 180 | + |
| 181 | + static void getRealUserPasswordUrl(String args[]) throws Exception { |
| 182 | + // URL can be modified in file, or taken from command-line |
| 183 | + url = getOptionValue(args, "-l", DEFAULT_URL); |
| 184 | + |
| 185 | + // DB user can be modified in file, or taken from command-line |
| 186 | + user = getOptionValue(args, "-u", DEFAULT_USER); |
| 187 | + |
| 188 | + // DB user's password can be modified in file, or explicitly entered |
| 189 | + readPassword(" Password for " + user + ": "); |
| 190 | + } |
| 191 | + |
| 192 | + // Get specified option value from command-line, or use default value |
| 193 | + static String getOptionValue(String args[], String optionName, |
| 194 | + String defaultVal) { |
| 195 | + String argValue = ""; |
| 196 | + |
| 197 | + try { |
| 198 | + int i = 0; |
| 199 | + String arg = ""; |
| 200 | + boolean found = false; |
| 201 | + |
| 202 | + while (i < args.length) { |
| 203 | + arg = args[i++]; |
| 204 | + if (arg.equals(optionName)) { |
| 205 | + if (i < args.length) |
| 206 | + argValue = args[i++]; |
| 207 | + if (argValue.startsWith("-") || argValue.equals("")) { |
| 208 | + argValue = defaultVal; |
| 209 | + } |
| 210 | + found = true; |
| 211 | + } |
| 212 | + } |
| 213 | + |
| 214 | + if (!found) { |
| 215 | + argValue = defaultVal; |
| 216 | + } |
| 217 | + } catch (Exception e) { |
| 218 | + showError("getOptionValue", e); |
| 219 | + } |
| 220 | + return argValue; |
| 221 | + } |
| 222 | + |
| 223 | + static void readPassword(String prompt) throws Exception { |
| 224 | + if (System.console() == null) { |
| 225 | + BufferedReader r = new BufferedReader(new InputStreamReader(System.in)); |
| 226 | + shownln(prompt); |
| 227 | + password = r.readLine(); |
| 228 | + } else { |
| 229 | + char[] pchars = System.console().readPassword("\n[%s]", prompt); |
| 230 | + if (pchars != null) { |
| 231 | + password = new String(pchars); |
| 232 | + java.util.Arrays.fill(pchars, ' '); |
| 233 | + } |
| 234 | + } |
| 235 | + } |
| 236 | + |
| 237 | + private static void show(String msg) { |
| 238 | + System.out.println(msg); |
| 239 | + } |
| 240 | + |
| 241 | + // Show message line without new line |
| 242 | + private static void shownln(String msg) { |
| 243 | + System.out.print(msg); |
| 244 | + } |
| 245 | + |
| 246 | + static void showError(String msg, Throwable exc) { |
| 247 | + System.out.println(msg + " hit error: " + exc.getMessage()); |
| 248 | + } |
| 249 | +} |
0 commit comments