Passagem de Objetos
 entre Java e Oracle

Transformando e enviando
Pojos Java como parâmetros
para Procedures em PL/SQL
no Oracle.
?
Fatores:
PL/SQL !!! / Java? Hibernate WTF??

Contrato com a Oracle de longo prazo

Máquina BD mais potente e ociosa

Algumas definições de segurança

Desempenho (“idas” ao banco)
Como “era” feito:
String sql = "insert into contatos (nome,email)
values (?,?)";

PreparedStatement stmt = con.prepareStatement(sql);

stmt.setString(1, contato.getNome());
stmt.setString(2, contato.getEmail());

stmt.execute();
Como “era” feito:
Statment stmt = con.createStatement();

ResultSet rs;
rs = stmt.executeQuery("select * from contatos");

List<Contato> contatos = new ArrayList<Contato>();

while (rs.next()) {

    int id = rs.getString("id");
    String nome = rs.getString("nome");
    String email = rs.getString("email");

    Contato c = new Contato(id, nome, email);
    contatos.add(c);
}
Depois:
session.save(contato);
Como “era” feito:
String proc = "{call procInsereContato(?,?,?)}";

CallableStatement cs = con.prepareCall(proc);

cs.registerOutParameter(1, java.sql.Types.NUMERIC);
cs.setString(2, contato.getNome());
cs.setString(3, contato.getEmail());

cs.execute();

contato.setId(cs.getInt(1));
Como “era” feito:
CREATE OR REPLACE PROCEDURE procInsereContato(
      contatoId OUT Contatos.id%TYPE,
      contatoNome IN Contatos.nome%TYPE,
      contatoEmail IN Contatos.email%TYPE)
IS
BEGIN

 INSERT INTO Contatos (id, nome, email)
 VALUES (SQ_CON.NEXTVAL, contatoNome, contatoEmail)
 RETURNING id INTO contatoId;

END;
Como “era” feito:
public class PessoaBean {

  private   long idPessoa;
  private   Date dtNascimento;
  private   String nome;
  private   char sexo;
  private   int idNacionalidade;
  private   int idUF;
  private   int idNaturalidade;
  private   String naturalidadeExt;
  private   int idCor;
  private   int idEstadoCivil;
  private   String telResidencial;
  private   String telCelular;
  private   String telComercial;
  private   String email;
  private   boolean stAtivo;
  private   FiliacaoBean filiacaoBean;
Como “era” feito:
String proc = "{call
procCadastraPessoa(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,
?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?
,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)}";

CallableStatement cs = con.prepareCall(proc);

cs.setLong(1, pessoa.getIdPessoa());
cs.setDate(2, pessoa.getDtNascimento());
cs.setString(3, Character.toString(pessoa.getSexo()));
cs.setInt(4, pessoa.getIdNacionalidade());
cs.setInt(5, pessoa.getIdUF());
cs.setInt(6, pessoa.getIdNaturalidade());
cs.setString(7, pessoa.getNaturalidadeExt());
cs.setInt(8, pessoa.getIdCor());
cs.setInt(9, pessoa.getIdEstadoCivil());
cs.setString(10, pessoa.getTelResidencial());
String proc = "{call procCadastraPessoa(?)}";

   CallableStatement cs = con.prepareCall(proc);

   cs.setObject(1, pessoa);

   Pessoa p = cs.getObject(2);


PROCEDURE procCadastraPessoa(Pessoa IN p);
Bizzaro!?
ojdbc14.jar
Primeira versão
public class Bairro {

    private int id;
    private String nome;

    public final String getNome() {
       return nome;
    }
    public final void setNome(String nome) {
       this.nome = nome;
    }
    public final int getId() {
       return id;
    }
    public final void setId(int id) {
       this.id = id;
    }
}
Primeira versão
public class Bairro {

  private int id;
  private String nome;

  // getters e setters suprimidos

   public STRUCT toSTRUCT(OracleConnection oconn)
throws SQLException {
      ...
   }

   public void toBEAN(STRUCT struct) throws
SQLException {
      ...
   }
}
Primeira versão
public STRUCT toSTRUCT(OracleConnection oconn) throws
SQLException {

   StructDescriptor sd =
StructDescriptor.createDescriptor("TP_BAIRRO", oconn);

    Object[] attributes = {
       ( 0 >= this.id ? null : this.id ),
       ( "".equals(this.nome) ? null : this.nome )
    };

    return new STRUCT(sd, oconn, attributes);
}
Primeira versão
public void toBEAN(STRUCT struct) throws SQLException {

    if (null != struct) {
      Object[] attributes = struct.getOracleAttributes();

        if (null != attributes[0]) {
          this.setId(((NUMBER)attributes[0]).intValue());
        }

        if (null != attributes[1]) {
          this.setNome(((CHAR)attributes[1]).getString());
        }
    }
}
Primeira versão
                        DAO
String proc = "{call procCadastraBairro(?)}";

OracleCallableStatement cs = oconn.prepareCall(proc);

cs.setSTRUCT(1, bairro.toSTRUCT(oconn));
cs.registerOutParameter(1, OracleTypes.STRUCT,
"TP_BAIRRO");

cs.execute();

bairro.toBEAN(cs.getSTRUCT(1));
Primeira versão
                    ORACLE

CREATE OR REPLACE TYPE TP_BAIRRO AS OBJECT (
   id      NUMBER(3),
   nome    VARCHAR2(50)
);




GRANT EXECUTE ON TP_BAIRRO TO USUARIO;
Primeira versão
                    ORACLE
CREATE OR REPLACE PROCEDURE procCadastraBairro(
      bairro IN OUT TP_BAIRRO)
IS
BEGIN

 INSERT INTO Bairros (id, nome)
 VALUES (SQ_BAI.NEXTVAL, bairro.nome)
 RETURNING id INTO bairro.id;

END;
Primeira versão
                     ORACLE
CREATE OR REPLACE PROCEDURE procCadastraBairro(
      bairro IN OUT TP_BAIRRO)
IS
   bairroId Bairros.id%TYPE;
BEGIN
       INSERT INTO Bairros (id, nome)
       VALUES (SQ_BAI.NEXTVAL, bairro.nome)
       RETURNING id INTO bairroId;

       SELECT TP_BAIRRO(id, nome)
       INTO bairro
       FROM Bairros
       WHERE id = bairroId;
END;
Primeira versão
                 LISTA no DAO

String proc = "{call procPesquisarBairro(?,?)}";

OracleCallableStatement cs = oconn.prepareCall(proc);

cs.setSTRUCT(1, bairro.toSTRUCT(oconn));

cs.registerOutParameter(2, OracleTypes.ARRAY,
"TPLISTA_BAIRRO");

cs.execute();


                     CONTINUA...
Primeira versão
                  LISTA no DAO

ARRAY array = cs.getARRAY(2);

Datum[] lista = array.getOracleArray();

List<Bairro> bairros = new ArrayList<Bairro>();

for (int i = 0; i < lista.length; i++) {
   Bairro bairro = new Bairro();
   bairro.toBEAN((STRUCT)lista[i]);
   bairros.add(bairro);
}

return bairros;
Primeira versão
                    ORACLE

CREATE OR REPLACE TYPE TPLISTA_BAIRRO AS TABLE OF
TP_BAIRRO;




GRANT EXECUTE ON TPLISTA_BAIRRO TO USUARIO;
Primeira versão
                    ORACLE

CREATE OR REPLACE TYPE TPLISTA_BAIRRO AS TABLE OF
NUMBER;

CREATE OR REPLACE TYPE TP_BAIRRO AS OBJECT ();

/** Objetos desfeitos / inicio reconstrucao **/

CREATE OR REPLACE TYPE TP_BAIRRO AS OBJECT (
   id      NUMBER(3),
   nome    VARCHAR2(50)
);

CREATE OR REPLACE TYPE TPLISTA_BAIRRO AS TABLE OF
TP_BAIRRO;
Primeira versão
                    ORACLE
CREATE OR REPLACE PROCEDURE procPesquisarBairro(
      bairro IN TP_BAIRRO,
      listaBairros OUT TPLISTA_BAIRRO)
IS
BEGIN
       SELECT TP_BAIRRO(id, nome)
       BULK COLLECT INTO listaBairros
       FROM Bairros
       WHERE nome = bairro.nome;
END;
Primeira versão
              ORACLE

SELECT VALUE(e)
BULK COLLECT INTO listaBairros
FROM TABLE( CAST( MULTISET(

    SELECT id, nome
    FROM Bairros
    WHERE nome = bairro.nome

) AS TPLISTA_BAIRRO)) e;
Primeira versão
                     toSTRUCT()
Object[] attributes = {

     int/long, // NUMBER
     String, // VARCHAR2
     boolean ? 1 : 0, // NUMBER(1)
     3 estados ? 1 : 0 : null, // NUMBER(1)
     util.Date ? new Timestamp(date.getTime()), // DATE
     OutroTipo.toSTRUCT(oconn), // TP_OUTROTIPO
     String ? CLOB.getEmptyCLOB(), // CLOB
     listaOutroTipoArray // TPLISTA_OUTROTIPO

};
Primeira versão
                   toSTRUCT()
ARRAY listaOutroTipoArray = null;

ArrayDescriptor ad =
ArrayDescriptor.createDescriptor("TPLISTA_OUTROTIPO",
oconn);

List<Object> listaItems = new ArrayList<Object>();

  for (OutroTipo outro : this.listaOutroTipo) {
     listaItems.add(outro.toSTRUCT(oconn));
  }

listaOutroTipoArray =
        new ARRAY(ad, oconn, listaItems.toArray());
}
Primeira versão
                     toBEAN()
Object[] valores = struct.getOracleAttributes();

((NUMBER)valores[0]).intValue();
((NUMBER)valores[1]).longValue();
((CHAR)valores[2]).getString();
((NUMBER)valores[3]).booleanValue();
((DATE)valores[4]).timestampValue();

this.outroTipo = new OutroTipo();
this.outroTipo.toBEAN((STRUCT)valores[5]);
Primeira versão
                    toBEAN()
CLOB cl = ((CLOB)valores[6]);

Reader reader = cl.characterStreamValue();
StringBuffer sb = new StringBuffer();

int nchars = 0;
char[] buffer = new char[10];

while((nchars = reader.read(buffer)) != -1) {
     sb.append(buffer, 0, nchars);
}
reader.close();

this.setDescricao(sb.toString());
Primeira versão
                    toBEAN()

this.listaOutroTipo = new ArrayList<OutroTipo>();

Datum[] lista = ((ARRAY)valores[7]).getOracleArray();

for (int i = 0; i < lista.length; i++) {
   OutroTipo outro = new OutroTipo();
   outro.toBEAN((STRUCT)lista[i]);
   this.listaOutroTipo.add(outro);
}
Primeira versão
import   java.io.IOException;
import   java.io.Reader;
import   java.sql.SQLException;
import   java.util.ArrayList;
import   java.util.Date;
import   java.util.List;

import   oracle.jdbc.OracleConnection;
import   oracle.sql.ARRAY;
import   oracle.sql.ArrayDescriptor;
import   oracle.sql.CHAR;
import   oracle.sql.CLOB;
import   oracle.sql.DATE;
import   oracle.sql.Datum;
import   oracle.sql.NUMBER;
import   oracle.sql.STRUCT;
import   oracle.sql.StructDescriptor;
Bizzaro!?
OracleTypeConverter
@ DBType(value)
@ NotInType
@ SendNull
OracleTypeConverter
STRUCTPrinter
OracleTypeConverter
@DBType("TP_BAIRRO")
public class Bairro {

    private int id;
    private String nome;

    // getters e setters suprimidos
}
OracleTypeConverter
                        DAO
String proc = "{call procCadastraBairro(?)}";

OracleCallableStatement cs = oconn.prepareCall(proc);

cs.setSTRUCT(1, OracleTypeConverter.toSTRUCT(oconn,
bairro));

cs.registerOutParameter(1, OracleTypes.STRUCT,
OracleTypeConverter.getDBTypeAnnotation(Bairro.class));

cs.execute();

bairro = OracleTypeConverter.toBEAN(Bairro.class,
cs.getSTRUCT(1));
OracleTypeConverter
                 LISTA no DAO
cs.setARRAY(1, OracleTypeConverter.toARRAY(oconn,
listaBairros, "TPLISTA_BAIRRO"));

cs.registerOutParameter(2, OracleTypes.ARRAY,
"TPLISTA_BAIRRO");

cs.execute();

listaBairros =
OracleTypeConverter.toList(Bairro.class,cs.getARRAY(2))
;
OracleTypeConverter
@DBType("TP_PAGINACAO")
public class Paginacao {

    private int pagina = 1;
    private int quantRegistros = 10;

    @SendNull
    private int total;

    @NotInType
    private String action;

    @DBType("TRISTATES")
    private String ativo;

    // getters e setters suprimidos
}
OracleTypeConverter
                    ORACLE

CREATE OR REPLACE TYPE TP_PAGINACAO AS OBJECT (
   pagina           NUMBER,
   quantRegistros   NUMBER,
   total            NUMBER,
   ativo            NUMBER(1)
);
OracleTypeConverter
@DBType("TP_OCORRENCIA")
public class Ocorrencia {

  private   Long id;
  private   Assunto assunto;
  private   Date dataCadastro;
  private   boolean stImprimirCarta;

  @DBType("CLOB")
  private String descricao;

  @DBType("TPLISTA_ENCAMINHAMENTO")
  private List<Encaminhamento> listaEncaminhamento;

  @SendNull
  @DBType("TPLISTA_LOTEIMPRESSAO")
  private List<LoteImpressao> listaLoteImpressao;
OracleTypeConverter
                    ORACLE

CREATE OR REPLACE TYPE   TP_OCORRENCIA AS OBJECT (
   id                    NUMBER,
   assunto               TP_ASSUNTO,
   dataCadastro          DATE,
   stImprimirCarta       NUMBER(1),
   descricao             CLOB,
   listaEncaminhamento   TPLISTA_ENCAMINHAMENTO,
   listaLoteImpressao    TPLISTA_LOTEIMPRESSAO
);
OracleTypeConverter
                DAO – Enviar CLOB
cs.setSTRUCT(1, OracleTypeConverter.toSTRUCT(oconn,
ocorrencia));

cs.registerOutParameter(2, OracleTypes.CLOB);

cs.execute();

CLOB clob = cs.getCLOB(2);
Writer sw = clob.setCharacterStream(1L);

sw.write(ob.getDescricao().trim().toCharArray());
sw.flush();
sw.close();
OracleTypeConverter
OracleTypeConverter
Não converte FLOAT, DOUBLE, BigDecimal, BigInteger
(ainda não precisei destes);

A converão é baseada na ordem dos atributos;

Cuidado com o tamanho da String para VARCHAR(?) e
do Integer para NUMBER(?);

Até o java 1.6 não existe suporte para o tipo Boolean do
PL/SQL;

Necessita de refatoração urgente!!!
Referências
Oracle Database JDBC Developer's Guide and Reference:

Working with Oracle Object Types
http://download.oracle.com/docs/cd/B19306_01/java.102/b14355/oraoot.htm


Using PL/SQL Collections and Records
http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14261/collections.htm


Oracle Database JPublisher User's Guide:

Introduction to JPublisher
http://download.oracle.com/docs/cd/B19306_01/java.102/b14188/intro.htm


Introduction to JPublisher # JDBC Mapping
http://download.oracle.com/docs/cd/B19306_01/java.102/b14188/intro.htm#sthref50
Obrigado!
André Luis F. Reis

arghos@gmail.com

twitter.com/andrelfreis

facebook.com/andrelfreis

linkedin.com/in/andrelfreis

Passagem de Objetos entre Java e Oracle

  • 1.
    Passagem de Objetos entre Java e Oracle Transformando e enviando Pojos Java como parâmetros para Procedures em PL/SQL no Oracle.
  • 2.
  • 3.
    Fatores: PL/SQL !!! /Java? Hibernate WTF?? Contrato com a Oracle de longo prazo Máquina BD mais potente e ociosa Algumas definições de segurança Desempenho (“idas” ao banco)
  • 4.
    Como “era” feito: Stringsql = "insert into contatos (nome,email) values (?,?)"; PreparedStatement stmt = con.prepareStatement(sql); stmt.setString(1, contato.getNome()); stmt.setString(2, contato.getEmail()); stmt.execute();
  • 5.
    Como “era” feito: Statmentstmt = con.createStatement(); ResultSet rs; rs = stmt.executeQuery("select * from contatos"); List<Contato> contatos = new ArrayList<Contato>(); while (rs.next()) { int id = rs.getString("id"); String nome = rs.getString("nome"); String email = rs.getString("email"); Contato c = new Contato(id, nome, email); contatos.add(c); }
  • 6.
  • 7.
    Como “era” feito: Stringproc = "{call procInsereContato(?,?,?)}"; CallableStatement cs = con.prepareCall(proc); cs.registerOutParameter(1, java.sql.Types.NUMERIC); cs.setString(2, contato.getNome()); cs.setString(3, contato.getEmail()); cs.execute(); contato.setId(cs.getInt(1));
  • 8.
    Como “era” feito: CREATEOR REPLACE PROCEDURE procInsereContato( contatoId OUT Contatos.id%TYPE, contatoNome IN Contatos.nome%TYPE, contatoEmail IN Contatos.email%TYPE) IS BEGIN INSERT INTO Contatos (id, nome, email) VALUES (SQ_CON.NEXTVAL, contatoNome, contatoEmail) RETURNING id INTO contatoId; END;
  • 9.
    Como “era” feito: publicclass PessoaBean { private long idPessoa; private Date dtNascimento; private String nome; private char sexo; private int idNacionalidade; private int idUF; private int idNaturalidade; private String naturalidadeExt; private int idCor; private int idEstadoCivil; private String telResidencial; private String telCelular; private String telComercial; private String email; private boolean stAtivo; private FiliacaoBean filiacaoBean;
  • 10.
    Como “era” feito: Stringproc = "{call procCadastraPessoa(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?, ?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,? ,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)}"; CallableStatement cs = con.prepareCall(proc); cs.setLong(1, pessoa.getIdPessoa()); cs.setDate(2, pessoa.getDtNascimento()); cs.setString(3, Character.toString(pessoa.getSexo())); cs.setInt(4, pessoa.getIdNacionalidade()); cs.setInt(5, pessoa.getIdUF()); cs.setInt(6, pessoa.getIdNaturalidade()); cs.setString(7, pessoa.getNaturalidadeExt()); cs.setInt(8, pessoa.getIdCor()); cs.setInt(9, pessoa.getIdEstadoCivil()); cs.setString(10, pessoa.getTelResidencial());
  • 12.
    String proc ="{call procCadastraPessoa(?)}"; CallableStatement cs = con.prepareCall(proc); cs.setObject(1, pessoa); Pessoa p = cs.getObject(2); PROCEDURE procCadastraPessoa(Pessoa IN p);
  • 15.
  • 16.
  • 17.
    Primeira versão public classBairro { private int id; private String nome; public final String getNome() { return nome; } public final void setNome(String nome) { this.nome = nome; } public final int getId() { return id; } public final void setId(int id) { this.id = id; } }
  • 18.
    Primeira versão public classBairro { private int id; private String nome; // getters e setters suprimidos public STRUCT toSTRUCT(OracleConnection oconn) throws SQLException { ... } public void toBEAN(STRUCT struct) throws SQLException { ... } }
  • 19.
    Primeira versão public STRUCTtoSTRUCT(OracleConnection oconn) throws SQLException { StructDescriptor sd = StructDescriptor.createDescriptor("TP_BAIRRO", oconn); Object[] attributes = { ( 0 >= this.id ? null : this.id ), ( "".equals(this.nome) ? null : this.nome ) }; return new STRUCT(sd, oconn, attributes); }
  • 20.
    Primeira versão public voidtoBEAN(STRUCT struct) throws SQLException { if (null != struct) { Object[] attributes = struct.getOracleAttributes(); if (null != attributes[0]) { this.setId(((NUMBER)attributes[0]).intValue()); } if (null != attributes[1]) { this.setNome(((CHAR)attributes[1]).getString()); } } }
  • 21.
    Primeira versão DAO String proc = "{call procCadastraBairro(?)}"; OracleCallableStatement cs = oconn.prepareCall(proc); cs.setSTRUCT(1, bairro.toSTRUCT(oconn)); cs.registerOutParameter(1, OracleTypes.STRUCT, "TP_BAIRRO"); cs.execute(); bairro.toBEAN(cs.getSTRUCT(1));
  • 22.
    Primeira versão ORACLE CREATE OR REPLACE TYPE TP_BAIRRO AS OBJECT ( id NUMBER(3), nome VARCHAR2(50) ); GRANT EXECUTE ON TP_BAIRRO TO USUARIO;
  • 23.
    Primeira versão ORACLE CREATE OR REPLACE PROCEDURE procCadastraBairro( bairro IN OUT TP_BAIRRO) IS BEGIN INSERT INTO Bairros (id, nome) VALUES (SQ_BAI.NEXTVAL, bairro.nome) RETURNING id INTO bairro.id; END;
  • 24.
    Primeira versão ORACLE CREATE OR REPLACE PROCEDURE procCadastraBairro( bairro IN OUT TP_BAIRRO) IS bairroId Bairros.id%TYPE; BEGIN INSERT INTO Bairros (id, nome) VALUES (SQ_BAI.NEXTVAL, bairro.nome) RETURNING id INTO bairroId; SELECT TP_BAIRRO(id, nome) INTO bairro FROM Bairros WHERE id = bairroId; END;
  • 25.
    Primeira versão LISTA no DAO String proc = "{call procPesquisarBairro(?,?)}"; OracleCallableStatement cs = oconn.prepareCall(proc); cs.setSTRUCT(1, bairro.toSTRUCT(oconn)); cs.registerOutParameter(2, OracleTypes.ARRAY, "TPLISTA_BAIRRO"); cs.execute(); CONTINUA...
  • 26.
    Primeira versão LISTA no DAO ARRAY array = cs.getARRAY(2); Datum[] lista = array.getOracleArray(); List<Bairro> bairros = new ArrayList<Bairro>(); for (int i = 0; i < lista.length; i++) { Bairro bairro = new Bairro(); bairro.toBEAN((STRUCT)lista[i]); bairros.add(bairro); } return bairros;
  • 27.
    Primeira versão ORACLE CREATE OR REPLACE TYPE TPLISTA_BAIRRO AS TABLE OF TP_BAIRRO; GRANT EXECUTE ON TPLISTA_BAIRRO TO USUARIO;
  • 28.
    Primeira versão ORACLE CREATE OR REPLACE TYPE TPLISTA_BAIRRO AS TABLE OF NUMBER; CREATE OR REPLACE TYPE TP_BAIRRO AS OBJECT (); /** Objetos desfeitos / inicio reconstrucao **/ CREATE OR REPLACE TYPE TP_BAIRRO AS OBJECT ( id NUMBER(3), nome VARCHAR2(50) ); CREATE OR REPLACE TYPE TPLISTA_BAIRRO AS TABLE OF TP_BAIRRO;
  • 29.
    Primeira versão ORACLE CREATE OR REPLACE PROCEDURE procPesquisarBairro( bairro IN TP_BAIRRO, listaBairros OUT TPLISTA_BAIRRO) IS BEGIN SELECT TP_BAIRRO(id, nome) BULK COLLECT INTO listaBairros FROM Bairros WHERE nome = bairro.nome; END;
  • 30.
    Primeira versão ORACLE SELECT VALUE(e) BULK COLLECT INTO listaBairros FROM TABLE( CAST( MULTISET( SELECT id, nome FROM Bairros WHERE nome = bairro.nome ) AS TPLISTA_BAIRRO)) e;
  • 31.
    Primeira versão toSTRUCT() Object[] attributes = { int/long, // NUMBER String, // VARCHAR2 boolean ? 1 : 0, // NUMBER(1) 3 estados ? 1 : 0 : null, // NUMBER(1) util.Date ? new Timestamp(date.getTime()), // DATE OutroTipo.toSTRUCT(oconn), // TP_OUTROTIPO String ? CLOB.getEmptyCLOB(), // CLOB listaOutroTipoArray // TPLISTA_OUTROTIPO };
  • 32.
    Primeira versão toSTRUCT() ARRAY listaOutroTipoArray = null; ArrayDescriptor ad = ArrayDescriptor.createDescriptor("TPLISTA_OUTROTIPO", oconn); List<Object> listaItems = new ArrayList<Object>(); for (OutroTipo outro : this.listaOutroTipo) { listaItems.add(outro.toSTRUCT(oconn)); } listaOutroTipoArray = new ARRAY(ad, oconn, listaItems.toArray()); }
  • 33.
    Primeira versão toBEAN() Object[] valores = struct.getOracleAttributes(); ((NUMBER)valores[0]).intValue(); ((NUMBER)valores[1]).longValue(); ((CHAR)valores[2]).getString(); ((NUMBER)valores[3]).booleanValue(); ((DATE)valores[4]).timestampValue(); this.outroTipo = new OutroTipo(); this.outroTipo.toBEAN((STRUCT)valores[5]);
  • 34.
    Primeira versão toBEAN() CLOB cl = ((CLOB)valores[6]); Reader reader = cl.characterStreamValue(); StringBuffer sb = new StringBuffer(); int nchars = 0; char[] buffer = new char[10]; while((nchars = reader.read(buffer)) != -1) { sb.append(buffer, 0, nchars); } reader.close(); this.setDescricao(sb.toString());
  • 35.
    Primeira versão toBEAN() this.listaOutroTipo = new ArrayList<OutroTipo>(); Datum[] lista = ((ARRAY)valores[7]).getOracleArray(); for (int i = 0; i < lista.length; i++) { OutroTipo outro = new OutroTipo(); outro.toBEAN((STRUCT)lista[i]); this.listaOutroTipo.add(outro); }
  • 36.
    Primeira versão import java.io.IOException; import java.io.Reader; import java.sql.SQLException; import java.util.ArrayList; import java.util.Date; import java.util.List; import oracle.jdbc.OracleConnection; import oracle.sql.ARRAY; import oracle.sql.ArrayDescriptor; import oracle.sql.CHAR; import oracle.sql.CLOB; import oracle.sql.DATE; import oracle.sql.Datum; import oracle.sql.NUMBER; import oracle.sql.STRUCT; import oracle.sql.StructDescriptor;
  • 37.
  • 40.
    OracleTypeConverter @ DBType(value) @ NotInType @SendNull OracleTypeConverter STRUCTPrinter
  • 41.
    OracleTypeConverter @DBType("TP_BAIRRO") public class Bairro{ private int id; private String nome; // getters e setters suprimidos }
  • 42.
    OracleTypeConverter DAO String proc = "{call procCadastraBairro(?)}"; OracleCallableStatement cs = oconn.prepareCall(proc); cs.setSTRUCT(1, OracleTypeConverter.toSTRUCT(oconn, bairro)); cs.registerOutParameter(1, OracleTypes.STRUCT, OracleTypeConverter.getDBTypeAnnotation(Bairro.class)); cs.execute(); bairro = OracleTypeConverter.toBEAN(Bairro.class, cs.getSTRUCT(1));
  • 43.
    OracleTypeConverter LISTA no DAO cs.setARRAY(1, OracleTypeConverter.toARRAY(oconn, listaBairros, "TPLISTA_BAIRRO")); cs.registerOutParameter(2, OracleTypes.ARRAY, "TPLISTA_BAIRRO"); cs.execute(); listaBairros = OracleTypeConverter.toList(Bairro.class,cs.getARRAY(2)) ;
  • 44.
    OracleTypeConverter @DBType("TP_PAGINACAO") public class Paginacao{ private int pagina = 1; private int quantRegistros = 10; @SendNull private int total; @NotInType private String action; @DBType("TRISTATES") private String ativo; // getters e setters suprimidos }
  • 45.
    OracleTypeConverter ORACLE CREATE OR REPLACE TYPE TP_PAGINACAO AS OBJECT ( pagina NUMBER, quantRegistros NUMBER, total NUMBER, ativo NUMBER(1) );
  • 46.
    OracleTypeConverter @DBType("TP_OCORRENCIA") public class Ocorrencia{ private Long id; private Assunto assunto; private Date dataCadastro; private boolean stImprimirCarta; @DBType("CLOB") private String descricao; @DBType("TPLISTA_ENCAMINHAMENTO") private List<Encaminhamento> listaEncaminhamento; @SendNull @DBType("TPLISTA_LOTEIMPRESSAO") private List<LoteImpressao> listaLoteImpressao;
  • 47.
    OracleTypeConverter ORACLE CREATE OR REPLACE TYPE TP_OCORRENCIA AS OBJECT ( id NUMBER, assunto TP_ASSUNTO, dataCadastro DATE, stImprimirCarta NUMBER(1), descricao CLOB, listaEncaminhamento TPLISTA_ENCAMINHAMENTO, listaLoteImpressao TPLISTA_LOTEIMPRESSAO );
  • 48.
    OracleTypeConverter DAO – Enviar CLOB cs.setSTRUCT(1, OracleTypeConverter.toSTRUCT(oconn, ocorrencia)); cs.registerOutParameter(2, OracleTypes.CLOB); cs.execute(); CLOB clob = cs.getCLOB(2); Writer sw = clob.setCharacterStream(1L); sw.write(ob.getDescricao().trim().toCharArray()); sw.flush(); sw.close();
  • 49.
  • 50.
    OracleTypeConverter Não converte FLOAT,DOUBLE, BigDecimal, BigInteger (ainda não precisei destes); A converão é baseada na ordem dos atributos; Cuidado com o tamanho da String para VARCHAR(?) e do Integer para NUMBER(?); Até o java 1.6 não existe suporte para o tipo Boolean do PL/SQL; Necessita de refatoração urgente!!!
  • 51.
    Referências Oracle Database JDBCDeveloper's Guide and Reference: Working with Oracle Object Types http://download.oracle.com/docs/cd/B19306_01/java.102/b14355/oraoot.htm Using PL/SQL Collections and Records http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14261/collections.htm Oracle Database JPublisher User's Guide: Introduction to JPublisher http://download.oracle.com/docs/cd/B19306_01/java.102/b14188/intro.htm Introduction to JPublisher # JDBC Mapping http://download.oracle.com/docs/cd/B19306_01/java.102/b14188/intro.htm#sthref50
  • 53.
    Obrigado! André Luis F.Reis arghos@gmail.com twitter.com/andrelfreis facebook.com/andrelfreis linkedin.com/in/andrelfreis