Fórum Classe Generica trabalhando com stored procedure #401911
28/05/2011
0
[COD]package treinamento.dao;import java.sql.Connection;import java.sql.DriverManager;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.sql.Statement;import java.util.logging.Level;import java.util.logging.Logger;
public abstract class GenericaDao {
private static final long serialVersionUID = 1L;
public Connection getConnection() { try { Class.forName("oracle.jdbc.OracleDriver"); Connection cx = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:XE","teste","teste"); return cx; } catch (Exception ex) { Logger.getLogger(GenericaDao.class.getName()).log(Level.SEVERE, null, ex); return null; } }
public Statement getStatement() throws SQLException { return getConnection().createStatement(); }
public PreparedStatement getStatement(String st) throws SQLException { return getConnection().prepareStatement(st); }
public ResultSet executeQuery(String query,Object... params) throws SQLException { PreparedStatement ps = getStatement(query); for (int i = 0; i < params.length; i++) { ps.setObject(i+1, params[i]); } return ps.executeQuery(); }
public int executeCommand(String query,Object... params) throws SQLException { PreparedStatement ps = getStatement(query); for (int i = 0; i < params.length; i++) { try { ps.setObject(i+1, params[i]); } catch (Exception e) { System.out.println("Error to try "+i+" with value "+params[i]); } } int result = ps.executeUpdate(); ps.close(); return result; }
}[/CODE]
Nilo Souza
Curtir tópico
+ 0Posts
28/05/2011
Anthony Accioly
Tem sim.
A API JDBC Possui CallableStatements (http://download.oracle.com/javase/6/docs/api/java/sql/CallableStatement.html) para fazer exatamente isso:
A sintaxe funciona assim:
#Código{?= call <procedure-name>[(<arg1>,<arg2>, ...)]}
Eis um exemplo de código fonte: http://www.java2s.com/Code/Java/Database-SQL-JDBC/CallStoredProcedureInOracleAndPassInOutParameters.htm
Para recuperar um cursor do Stored Procedure você vai ter que registrá-lo com a sequinte sintaxe antes de recuperar o ResultSet:
#CódigoregisterOutParameter(<nome-do-cursor>, OracleTypes.CURSOR);
Eis um exemplo: http://www.andrels.com/wp-en_US/index.php/2010/01/retieving-an-oracle-cursor-in-java/
Espero ter ajudado.
Abraços,
Gostei + 0
28/05/2011
Nilo Souza
Gostei + 0
28/05/2011
Anthony Accioly
Ok. Tendo uma dúvida mais específica pode perguntar.
No geral o CallableStatement é muito parecido com o PreparedStatement que você está usando nesse código.
Se você chegou a dar uma olhada no último exemplo, seu uso é bastante direto:
//Calling Oracle procedure
CallableStatement cs = conn.prepareCall("{call PAC_CURSOR.PRO_RETURN_CARS(?,?)}");
//Defining type of return
cs.registerOutParameter("o_cursor", OracleTypes.CURSOR);
cs.setLong("i_id", id);
cs.execute();//Running the call
//Retrieving the cursor as ResultSet
ResultSet rs = (ResultSet)cs.getObject("o_cursor");
//Iterating the returned rows
while(rs.next()){
//Getting column values
System.out.println("ID: " + rs.getLong("car_id"));
System.out.println("Manufacturer: " + rs.getString("company"));
System.out.println("Model: " + rs.getString("model"));
System.out.println("Color: " + rs.getString("color"));
System.out.println("HP: " + rs.getString("hp"));
System.out.println("Price: " + rs.getFloat("price"));
}
Eu não gosto muito desse padrão de sair percorrendo var-args de Objects e chamando setObject por índice (apesar de muitos frameworks fazerem isso...). Porém, é possível fazer uma adaptação trivial do seu método executeQuery para fazer o que você quer. Apenas troque a versão para obter uma CallableStatement da conexão, sete o parâmetro de saída para o cursor, faça uma chamada para execute e obtenha o ResultSet a partir do cursor. Tudo como no exemplo acima.
Gostei + 0
28/05/2011
Nilo Souza
se comecei a entender comecei a trilhar desse jeito.
MINHA CLASSE DE PROCEDURE GENERICA
package treinamento.dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.CallableStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.logging.Level;
import java.util.logging.Logger;
public abstract class GenericaDao_Proc {
private static final long serialVersionUID = 1L;
public Connection getConnection() {
try {
Class.forName("oracle.jdbc.OracleDriver");
Connection cx = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:XE","TESTE","TESTE");
return cx;
} catch (Exception ex) {
Logger.getLogger(GenericaDao_Proc.class.getName()).log(Level.SEVERE, null, ex);
return null;
}
}
public Statement getStatement() throws SQLException {
return getConnection().createStatement();
}
public PreparedStatement getPrepared(String st) throws SQLException {
return getConnection().prepareStatement(st);
}
public CallableStatement getCallableStatement(String st) throws SQLException{
return getConnection().prepareCall(st);
}
public ResultSet executeQuery(String query,Object... params) throws SQLException {
PreparedStatement ps = getPrepared(query);
for (int i = 0; i < params.length; i++) {
ps.setObject(i+1, params[i]);
}
return ps.executeQuery();
}
public int executePrepered(String query,Object... params) throws SQLException {
PreparedStatement ps = getCallableStatement(query);
for (int i = 0; i < params.length; i++) {
try {
ps.setObject(i+1, params[i]);
} catch (Exception e) {
System.out.println("Error to try "+i+" with value "+params[i]);
}
}
int result = ps.executeUpdate();
ps.close();
return result;
}
public int executeCommand(String query,Object... params) throws SQLException {
PreparedStatement ps = getPrepared(query);
for (int i = 0; i < params.length; i++) {
try {
ps.setObject(i+1, params[i]);
} catch (Exception e) {
System.out.println("Error to try "+i+" with value "+params[i]);
}
}
int result = ps.executeUpdate();
ps.close();
return result;
}
}
MINHA CLASSE DAO PARA INSERIR, ALTERAR E EXCLUIR
package treinamento.dao;
import treinamento.entidade.Usuario;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.List;
/**
*
* @author Nilo
*/
public class Usuario_Proc_Dao extends GenericaDao_Proc{
private static final long serialVersionUID = 1L;
public Usuario_Proc_Dao(){
}
public void addUsuarioProc(Usuario usr) throws SQLException {
String query = "{ call sp_restricoes(?,?,?,?,?,?,?) }";
executePrepered(query, usr.getNome(), usr.getLogin(), usr.getSenha(),usr.getId_grupo(),usr.getUsuario_incluir(),usr.getUsuario_altera());
}
public Usuario getUsuario(int idUsuario) throws SQLException {
ResultSet rs = executeQuery("SELECT * FROM USUARIO WHERE IDUSUARIO = ?", idUsuario);
Usuario usr = null;
if (rs.next()) {
usr = populateUsuarioInfo(rs);
}
rs.close();
return usr;
}
public List<Usuario> getAllUsuarios() throws SQLException {
ResultSet rs = executeQuery("SELECT * FROM USUARIO");
List<Usuario> toReturn = new LinkedList<Usuario>();
while (rs.next()) {
toReturn.add(populateUsuarioInfo(rs));
}
rs.close();
return toReturn;
}
public static Usuario populateUsuarioInfo(ResultSet rs) throws SQLException {
Usuario toReturn = new Usuario();
toReturn.setIdUsuario(rs.getInt("IDUSUARIO"));
toReturn.setLogin(rs.getString("LOGIN"));
toReturn.setNome(rs.getString("NOME"));
toReturn.setSenha(rs.getString("SENHA"));
toReturn.setId_grupo(rs.getInt("ID_GRUPO"));
toReturn.setUsuario_incluir(rs.getInt("USUARIO_INCLUI"));
toReturn.setUsuario_altera(rs.getInt("USUARIO_ALTERA"));
return toReturn;
}
}
Gostei + 0
28/05/2011
Nilo Souza
classe de teste
@Test
public void testAddUsuarioProc() throws Exception {
System.out.println("addUsuarioProc");
Usuario usr = new Usuario();
usr.setNome("Nilo Souza");
usr.setLogin("nsouza9");
usr.setSenha("123");
usr.setId_grupo(1);
usr.setUsuario_incluir(5);
Usuario_Proc_Dao instance = new Usuario_Proc_Dao();
instance.addUsuarioProc(usr);
}
METODO DA CLASSE DAO
public void addUsuarioProc(Usuario usr) throws SQLException {
String query = "{ call sp_restricoes(?,?,?,?,?,?,?) }";
executePrepered(query,0, usr.getNome(), usr.getLogin(), usr.getSenha(),usr.getId_grupo(),usr.getUsuario_incluir(),'I');
}
MENSAGEM DE ERRO DO TESTE
Testsuite: treinamento.dao.Usuario_Proc_DaoTest addUsuarioProc Error to try 6 with value I Tests run: 1, Failures: 0, Errors: 1, Time elapsed: 1,43 sec ------------- Standard Output --------------- addUsuarioProc Error to try 6 with value I ------------- ---------------- --------------- Testcase: testAddUsuarioProc(treinamento.dao.Usuario_Proc_DaoTest): Caused an ERROR Parâmetro IN ou OUT ausente do índice:: 7 java.sql.SQLException: Parâmetro IN ou OUT ausente do índice:: 7 at oracle.jdbc.driver.OraclePreparedStatement.processCompletedBindRow(OraclePreparedStatement.java:1821) at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3571) at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:3657) at oracle.jdbc.driver.OracleCallableStatement.executeUpdate(OracleCallableStatement.java:4739) at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeUpdate(OraclePreparedStatementWrapper.java:1350) at treinamento.dao.GenericaDao_Proc.executePrepered(GenericaDao_Proc.java:70) at treinamento.dao.Usuario_Proc_Dao.addUsuarioProc(Usuario_Proc_Dao.java:30) at treinamento.dao.Usuario_Proc_DaoTest.testAddUsuarioProc(Usuario_Proc_DaoTest.java:55) Test treinamento.dao.Usuario_Proc_DaoTest FAILED test: Deleting: /tmp/TEST-treinamento.dao.Usuario_Proc_DaoTest.xml BUILD SUCCESSFUL (total time: 2 seconds)
Gostei + 0
28/05/2011
Davi Costa
public void addUsuarioProc(Usuario usr) throws SQLException {
String query = "{ call sp_restricoes(?,?,?,?,?,?,?) }";
executePrepered(query, usr.getNome(), usr.getLogin(), usr.getSenha(),usr.getId_grupo(),usr.getUsuario_incluir(),usr.getUsuario_altera());
}
Mas aparentemente no seu teste vc não instancio todos esse atributos.
@Test
public void testAddUsuarioProc() throws Exception {
System.out.println("addUsuarioProc");
Usuario usr = new Usuario();
usr.setNome("Nilo Souza"); // confere
usr.setLogin("nsouza9"); //confere
usr.setSenha("123");//confere
usr.setId_grupo(1);//confere
usr.setUsuario_incluir(5);//confere
// mas o usr.getUsuario_altera()?
Usuario_Proc_Dao instance = new Usuario_Proc_Dao();
instance.addUsuarioProc(usr);
}
Att Davi
Gostei + 0
29/05/2011
Nilo Souza
Fiz conforme orientou e ficou desde jeito dando o erro abaixo:
Metodo alterado
public void addUsuarioProc(Usuario usr) throws SQLException { String query = "{ call sp_restricoes(?,?,?,?,?,?,?) }"; executePrepered(query,usr.getIdUsuario(), usr.getNome(), usr.getLogin(), usr.getSenha(),usr.getId_grupo(),usr.getUsuario_incluir(),usr.getOpr()); }Classe teste alterada
@Test public void testAddUsuarioProc() throws Exception { System.out.println("addUsuarioProc"); Usuario usr = new Usuario(); usr.setIdUsuario(0); usr.setNome("Nilo Souza"); usr.setLogin("nsouza9"); usr.setSenha("123"); usr.setId_grupo(1); usr.setUsuario_incluir(5); usr.setUsuario_altera(2); Usuario_Proc_Dao instance = new Usuario_Proc_Dao(); instance.addUsuarioProc(usr); }Erro ao testar a classe
Testsuite: treinamento.dao.Usuario_Proc_DaoTestaddUsuarioProcTests run: 1, Failures: 0, Errors: 1, Time elapsed: 1,775 sec ------------- Standard Output ---------------addUsuarioProc------------- ---------------- ---------------Testcase: testAddUsuarioProc(treinamento.dao.Usuario_Proc_DaoTest): Caused an ERRORORA-06550: linha 1, coluna 7:PLS-00306: número incorreto de tipos de argumentos na chamada para 'SP_RESTRICOES'ORA-06550: linha 1, coluna 7:PL/SQL: Statement ignored java.sql.SQLException: ORA-06550: linha 1, coluna 7:PLS-00306: número incorreto de tipos de argumentos na chamada para 'SP_RESTRICOES'ORA-06550: linha 1, coluna 7:PL/SQL: Statement ignored at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:440) at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396) at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:440) at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:837) at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:445) at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:191) at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:523) at oracle.jdbc.driver.T4CCallableStatement.doOall8(T4CCallableStatement.java:204) at oracle.jdbc.driver.T4CCallableStatement.executeForRows(T4CCallableStatement.java:1007) at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1315) at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3576) at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:3657) at oracle.jdbc.driver.OracleCallableStatement.executeUpdate(OracleCallableStatement.java:4739) at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeUpdate(OraclePreparedStatementWrapper.java:1350) at treinamento.dao.GenericaDao_Proc.executePrepered(GenericaDao_Proc.java:70) at treinamento.dao.Usuario_Proc_Dao.addUsuarioProc(Usuario_Proc_Dao.java:30) at treinamento.dao.Usuario_Proc_DaoTest.testAddUsuarioProc(Usuario_Proc_DaoTest.java:57) Test treinamento.dao.Usuario_Proc_DaoTest FAILEDtest:Deleting: /tmp/TEST-treinamento.dao.Usuario_Proc_DaoTest.xmlBUILD SUCCESSFUL (total time: 3 seconds)
Gostei + 0
29/05/2011
Anthony Accioly
Se esse é aquele procedure que você postou no fórum de Oracle, veja que ele só tem três argumentos. Não se esqueça de anotar os parâmetros com IN.
PROCEDURE sp_restricoes( ptabela IN NUMBER, popr IN VARCHAR2, pusuario IN VARCHAR2)
Nessa caso você teria que passar um número e duas Strings para a chamada do procedure.
String query = "{ call sp_restricoes(?,?,?) }Você pode setar tanto por posição quanto nome conforme exemplos anteriores.
Abraços
Gostei + 0
29/05/2011
Nilo Souza
Gostei + 0
Clique aqui para fazer login e interagir na Comunidade :)