Замена oracle "OracleTypes.CURSOR" на эквивалент в mysql при использовании функции registerOutParameter

Уважаемый коллектив stackoverflow

Я пытаюсь обновить систему, разработанную в JAVA, от использования Oracle до DB базы данных.

Я дошел до того, что для использования хранимой процедуры в Java-коде используется определенная структура оракула - OracleTypes.CURSOR. См. Код ниже.

private int getUserID(String username) {
 int UserID = -1;
 CallableStatement cs = null;
 ResultSet rs = null;
 try {
 con = this.getConnection();
 cs = con.prepareCall("{call getUserID(?,?)}");
 cs.setString(1, username);
 cs.registerOutParameter(2, OracleTypes.CURSOR);
 cs.execute();
 rs = (ResultSet) cs.getObject(2);

 if (rs.next()) {
 UserID = rs.getInt(1);
 }
 } catch (Exception e) {
 e.printStackTrace();
 } finally {
 try {
 cs.close();
 rs.close();
 } catch (SQLException ex) {
 Logger.getLogger(DBConnector.class.getName()).log(Level.SEVERE, null, ex);
 }
 closeConnection();
 return UserID;
 }
}

Я пытаюсь преобразовать использование OracleTypes.CURSOR в нечто дружественное mysql. Я прочитал, что было бы возможно сделать это в новой версии mysql, поэтому я даже попытался заменить OracleTypes.CURSOR на java.sql.Types.INTEGER без каких-либо результатов.

Вы можете мне помочь?

Примечание. У меня есть следующая информация о переполнении стека, а также в других местах: http://bugs.mysql.com/bug.php?id=17898

1 ответ

MySql, к сожалению, не реализует ref cursors. Однако хранимые процедуры в MySql могут возвращать набор результатов клиенту, см. Эту ссылку: http://dev.mysql.com/doc/refman/5.6/en/faqs-stored-procs.html#qandaitem-B-4- 1-14

B.4.14: Могут ли хранимые процедуры MySQL 5.6 возвращать наборы результатов? Сохраненные процедуры могут, но сохраненные функции не могут. Если вы выполняете обычный SELECT внутри хранимой процедуры, набор результатов возвращается непосредственно клиенту.

Просто запустите обычный SELECT - и результат возвращается клиенту. Resulset - очень похожая концепция для ref cursor в Oracle. Самое существенное различие заключается в том, что в MySql набор результатов полностью извлекается с сервера клиенту и сохраняется в памяти на стороне клиента (в то время как cursors Oracle извлекают строки в кусках). Однако MySql может имитировать это поведение (с некоторыми ограничениями), см. Эту ссылку: http://dev.mysql.com/doc/connector-j/en/connector-j-reference-implementation-notes.html

ResultSet По умолчанию ResultSets полностью извлекаются и сохраняются в памяти. В большинстве случаев это самый эффективный способ работы, и благодаря дизайну сетевого протокола MySQL проще реализовать. Если вы работаете с ResultSets, которые имеют большое количество строк или больших значений, и не могут выделить кучу пространства в вашей JVM для требуемой памяти, вы можете сообщить драйверу передать результаты назад по одной строке за раз.

Чтобы включить эту функцию, создайте экземпляр Statement следующим образом:

stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,
 java.sql.ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(Integer.MIN_VALUE);

Комбинация набора результатов только для чтения, доступного только для чтения, с размером выборки Integer.MIN_VALUE служит сигналом для драйвера для потоковых результирующих наборов строк за строкой. После этого любые результирующие наборы, созданные с помощью инструкции, будут загружаться по строкам.

Как это работает - пример. Скажем, у нас есть процедура оракула, которую мы хотим перенести на MySql:

create or replace procedure getUserId( p_name varchar2, p_ref OUT sys_refcursor )
is
begin
 open p_ref for
 select id, username from users
 where username = p_name;
end;
/

В MySql эта процедура может выглядеть так:

delimiter %%
drop procedure if exists getUserId %%
create procedure getUserId( p_name varchar(100) )
begin
 SELECT id, username FROM users
 WHERE username = p_name;
end;%%
delimiter ;

и код в Java - на основе примера из документации: http://dev.mysql.com/doc/connector-j/en/connector-j-usagenotes-statements-callable.html#connector-j-examples-retrieving- Результаты-PARAMS

cs = conn.prepareCall("{call getUserID(?)}");
 cs.setString(1, "user1");
 boolean hasResultSet = cs.execute();
 if( hasResultSet ){
 rs = cs.getResultSet();
 if (rs.next()) {
 userId = rs.getInt(1);
 }
 System.out.println( "Userid = " + userId );
 }

licensed under cc by-sa 3.0 with attribution.