<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>André L. S. &#187; Oracle</title>
	<atom:link href="http://www.andrels.com/wp-pt_BR/index.php/category/desenvolvimento/oracle/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.andrels.com/wp-pt_BR</link>
	<description>Desenvolvimento de Softwares, Tecnologia e Games</description>
	<lastBuildDate>Wed, 08 Feb 2012 12:37:50 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Compilando objetos inválidos do Oracle de maneira fácil</title>
		<link>http://www.andrels.com/wp-pt_BR/index.php/2012/01/compilando-objetos-invalidos-do-oracle-de-maneira-facil/#utm_source=feed&#038;utm_medium=feed&#038;utm_campaign=feed</link>
		<comments>http://www.andrels.com/wp-pt_BR/index.php/2012/01/compilando-objetos-invalidos-do-oracle-de-maneira-facil/#comments</comments>
		<pubDate>Mon, 02 Jan 2012 21:39:46 +0000</pubDate>
		<dc:creator>André</dc:creator>
				<category><![CDATA[Dicas rápidas]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Tutoriais]]></category>
		<category><![CDATA[plsql]]></category>

		<guid isPermaLink="false">http://www.andrels.com/wp-pt_BR/?p=454</guid>
		<description><![CDATA[Quando se compila um objeto que é referenciado por vários outros objetos, estes ficam inválidos até que sejam recompilados novamente,<a href="http://www.andrels.com/wp-pt_BR/index.php/2012/01/compilando-objetos-invalidos-do-oracle-de-maneira-facil/" class="searchmore">Read the Rest...</a><div class="clr"></div>]]></description>
			<content:encoded><![CDATA[<p>Quando se compila um objeto que é referenciado por vários outros objetos, estes ficam inválidos até que sejam recompilados novamente, coisa que o Oracle deveria fazer e, de alguma maneira, as vezes não faz.</p>
<p>Então aqui vai uma dica para quem tem de compilar várias <em>packages</em>, <em>procedures</em> e/ou <em>functions</em> inválidas diariamente devido à esta falha do Oracle.</p>
<p>Existe um comando que força o banco a compilar todos os objetos inválidos sob um determinado usuário, o comando é:</p>
<pre class="brush:sql">exec dbms_ultility.compile_schema(&lt;USUARIO&gt;);</pre>
<p>Substitua por <i>user</i> onde está &lt;USUARIO&gt; se os objetos estiverem sob o usuário que está conectado, ou pelo nome de usuário correspondente.</p>
<p>O comando demora um pouco para ser executado e não compila todos os objetos que estão inválidos por erro de codificação, para descobrir quais objetos estão inválidos, você pode executar a seguinte <em>query</em>:</p>
<pre class="brush:sql">
select object_name
from all_objects
where status = 'INVALID'
</pre>
<p>Será listado os objetos que estão inválidos na base.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.andrels.com/wp-pt_BR/index.php/2012/01/compilando-objetos-invalidos-do-oracle-de-maneira-facil/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>INNER JOIN e OUTER JOIN</title>
		<link>http://www.andrels.com/wp-pt_BR/index.php/2010/07/inner-join-e-outer-join/#utm_source=feed&#038;utm_medium=feed&#038;utm_campaign=feed</link>
		<comments>http://www.andrels.com/wp-pt_BR/index.php/2010/07/inner-join-e-outer-join/#comments</comments>
		<pubDate>Fri, 30 Jul 2010 14:02:17 +0000</pubDate>
		<dc:creator>André</dc:creator>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Tutoriais]]></category>
		<category><![CDATA[inner join]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[outer join]]></category>
		<category><![CDATA[postgresql]]></category>
		<category><![CDATA[sql]]></category>
		<category><![CDATA[sql server]]></category>

		<guid isPermaLink="false">http://www.andrels.com/wp-pt_BR/?p=244</guid>
		<description><![CDATA[Se você é um DBA ou trabalha com programação e usa muito banco de dados SQL, este tópico não é<a href="http://www.andrels.com/wp-pt_BR/index.php/2010/07/inner-join-e-outer-join/" class="searchmore">Read the Rest...</a><div class="clr"></div>]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Se você é um DBA ou trabalha com programação e usa muito banco de dados SQL, este tópico não é você, a menos que não conheça as cláusulas INNER JOIN e OUTER JOIN, muito comuns em SGBDs SQL.</p>
<p style="text-align: justify;">Não sabe o que é SGBD? Os <strong>S</strong>istemas de <strong>G</strong>erenciamento de <strong>B</strong>anco de <strong>D</strong>ados são programas que auxiliam na manipulação dos dados armazenados. O MySQL, PostgreSQL, MS SQL Server ou Oracle, que você tem em sua casa ou empresa, são SGBDs.</p>
<p style="text-align: justify;">Para este tutorial você precisa ter, pelo menos, o conhecimento básico de SQL.</p>
<p style="text-align: justify;">Chega de enrolação, vamos ao que interessa!</p>
<h4>INNER JOIN</h4>
<p style="text-align: justify;">A cláusula INNER JOIN é usada quando se quer recuperar dados em mais de uma tabela através da igualdade de suas <em>foreign keys</em>.</p>
<p style="text-align: justify;">Por exemplo, pense que você quer criar um programa que sirva como agenda telefônica. Você cadastra as pessoas e os contatos telefônicos, como uma pessoa poderá ter nenhum até N números de telefones, você separa em duas entidades como neste modelo:<br />
<img class="aligncenter size-full wp-image-247" title="post - ptg" src="http://www.andrels.com/wp-pt_BR/wp-content/uploads/2010/07/post-ptg.jpg" alt="" width="197" height="249" /></p>
<p style="text-align: justify;">Olhando rapidamente você percebe que a entidade TELEFONE tem o atributo <strong>NUM_PESSOA</strong> que é o número de identificação do registro na entidade PESSOA.</p>
<p style="text-align: justify;">Vamos supor que as tabelas estejam preenchidas com os seguintes registros:</p>
<pre> +----------------------------+  +---------------------------+
 |           PESSOA           |  |         CONTATO           |
 +------------+---------------+  +------------+--------------+
 | NUM_PESSOA | NOME_PESSOA   |  | NUM_PESSOA | NUM_TELEFONE |
 | 1          | José          |  | 1          | 6589-3666    |
 | 2          | Arnaldo       |  | 3          | 9888-6699    |
 | 3          | Maria         |  | 3          | 8956-6666    |
 | 4          | Elverdelando  |  | 2          | 2888-9877    |
 +------------+---------------+  +------------+--------------+</pre>
<p style="text-align: justify;">Para recuperar os telefones de uma pessoa você deve usar INNER JOIN, implicitamente ou explicitamente. Vou explicar os dois casos.</p>
<p style="text-align: justify;">O método <strong>explícito</strong> é usar a cláusula explicitamente (duh!), que é formada por <strong>INNER JOIN </strong><em>&lt;tabela filha&gt;</em><strong> ON </strong><em>&lt;atributos de identificação&gt;</em>, no nosso exemplo:</p>
<pre class="brush:sql">SELECT nome_completo, num_telefone FROM pessoa INNER JOIN telefone <strong>ON</strong> pessoa.num_pessoa = telefone.num_pessoa</pre>
<p style="text-align: justify;">Estamos dizendo: &#8220;me traga o nome e os números dos telefones da pessoa onde o número da pessoa em TELEFONE seja igual ao número da pessoa em PESSOA&#8221;.</p>
<p style="text-align: justify;">Na forma <strong>implícita</strong> você não usa a cláusula INNER JOIN, o tratamento de igualdade é feito na cláusula <strong>WHERE</strong>. Usando o mesmo exemplo:</p>
<pre class="brush:sql">SELECT nome_completo, num_telefone FROM pessoa, telefone WHERE pessoa.num_pessoa = telefone.num_pessoa</pre>
<p style="text-align: justify;">Em ambos os casos o resultado será:</p>
<pre> +---------------------------+
 |         CONTATO           |
 +------------+--------------+
 | NOM_PESSOA | NUM_TELEFONE |
 | José       | 6589-3666    |
 | Maria      | 9888-6699    |
 | Maria      | 8956-6666    |
 | Arnaldo    | 2888-9877    |
 +------------+--------------+</pre>
<p style="text-align: justify;">&#8220;Que simples! Hummmm espera um pouco&#8230; Onde está o Elverdelando (que nominho, hein?!).&#8221;</p>
<p style="text-align: justify;">Lembra que dissemos ao banco &#8220;me traga o nome e os números dos telefones da pessoa onde o número da pessoa em TELEFONE seja igual ao número da pessoa em PESSOA&#8221;? Então! O Elverdelando não esta na tabela TELEFONE, por isso não foi retornado no resultado.</p>
<p style="text-align: justify;">Quando você precisar retornar os dados, mesmo não estando na tabela filha, usamos o <strong>OUTER JOIN</strong>.</p>
<h4>OUTER JOIN</h4>
<p style="text-align: justify;">A clásula OUTER JOIN tem duas variantes, <strong>LEFT OUTER JOIN</strong> e <strong>RIGHT OUTER JOIN</strong>, sendo que estas cláusula devem ser declaradas sempre de maneira explícita. Alguns SGBDs facilitam a utilização do OUTER JOIN te polpando de declarar toda a sintaxe, como é o caso do Oracle que utiliza o símbolo <strong>(+)</strong> na identificação fraca, mas <strong>NÃO É ANSI</strong>, ou seja, não funcionará em qualquer SGBD.</p>
<p style="text-align: justify;">Para que apareçam todas as pessoas, inclusive as que não têm número de telefone cadastrado usamos <strong>LEFT OUTER JOIN</strong> ou <strong>RIGHT OUTER JOIN</strong>.</p>
<p style="text-align: justify;">A sintaxe é parecida com a INNER JOIN, mudando apenas o nome da cláusula: <strong>LEFT[RIGHT] OUTER JOIN </strong><em>&lt;tabela filha&gt;</em><strong> ON </strong><em>&lt;atributos de identificação&gt;;</em></p>
<p style="text-align: justify;">Assim, faremos&#8230;</p>
<pre class="brush:sql">SELECT nome_completo, num_telefone FROM pessoa LEFT OUTER JOIN telefone ON pessoa.num_pessoa = telefone.num_pessoa</pre>
<p>ou então</p>
<pre class="brush:sql">SELECT nome_completo, num_telefone FROM telefone RIGHT OUTER JOIN pessoa ON pessoa.num_pessoa = telefone.num_pessoa</pre>
<p style="text-align: justify;">Em ambos os casos o resultado será:</p>
<pre> +-----------------------------+
 |         CONTATO             |
 +--------------+--------------+
 | NOM_PESSOA   | NUM_TELEFONE |
 | José         | 6589-3666    |
 | Maria        | 9888-6699    |
 | Maria        | 8956-6666    |
 | Arnaldo      | 2888-9877    |
 | Elverdelando |              |
 +--------------+--------------+</pre>
<p style="text-align: justify;">Como você pôde perceber, a única diferença entre o <strong>LEFT OUTER JOIN</strong> e o <strong>RIGHT OUTER JOIN</strong> é só a indicação de qual é o lado forte do relacionamento, ou seja, em qual lado da cláusula está a tabela que pode não ter valores na tabela filha. No nosso caso, ambos apontando para a tabela PESSOA.</p>
<p style="text-align: justify;"><em>INNER JOIN</em> é muito usado para consulta em banco de dados, quase que totalmente em seu método implícito. Já as cláusulas <em>OUTER JOIN</em> também são usadas, mas não com tanta frequência, posso dizer que é raro encontra-las por aí.</p>
<p style="text-align: justify;">Espero que este tutorial os ajude! <img src='http://www.andrels.com/wp-pt_BR/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.andrels.com/wp-pt_BR/index.php/2010/07/inner-join-e-outer-join/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Recuperando cursor de uma procedure do Oracle no Java</title>
		<link>http://www.andrels.com/wp-pt_BR/index.php/2010/01/recuperando-cursor-de-uma-procedure-do-oracle-no-java/#utm_source=feed&#038;utm_medium=feed&#038;utm_campaign=feed</link>
		<comments>http://www.andrels.com/wp-pt_BR/index.php/2010/01/recuperando-cursor-de-uma-procedure-do-oracle-no-java/#comments</comments>
		<pubDate>Mon, 18 Jan 2010 01:07:32 +0000</pubDate>
		<dc:creator>André</dc:creator>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Tutoriais]]></category>

		<guid isPermaLink="false">http://www.andrels.com/wp-pt_BR/?p=145</guid>
		<description><![CDATA[Percebi que muitas pessoas acabam chegando aqui pesquisando uma forma de recuperar cursores através de procedures do Oracle, para estas<a href="http://www.andrels.com/wp-pt_BR/index.php/2010/01/recuperando-cursor-de-uma-procedure-do-oracle-no-java/" class="searchmore">Read the Rest...</a><div class="clr"></div>]]></description>
			<content:encoded><![CDATA[<p>Percebi que muitas pessoas acabam chegando aqui pesquisando uma forma de recuperar cursores através de <em>procedures</em> do Oracle, para estas pessoas eu coloco à disposição uma maneira de fazê-lo.</p>
<p>Para que o cursor possa ser retornado é preciso declara-lo como <em>REF CURSOR</em> no <em>spec</em> da <em>Package</em>.</p>
<pre class="brush:sql">  --Criando o tipo REF CURSOR que será o cursor
  type g_cursor is ref cursor;</pre>
<p>Em ambos, <em>spec</em> e <em>body</em>, você precisa declarar uma variável <em>out</em> do tipo do <em>REF CURSOR</em> mencionado acima.</p>
<pre class="brush:sql">  procedure PRO_RETORNA_LISTA_CARROS(
    i_id     in     tbl_car.car_id%type,
    o_cursor in out g_cursor);</pre>
<p>Para devolver o cursor com os resultados (caso haja), é necessário abri-lo no <em>body</em> da <em>procedure</em>, desta forma:</p>
<pre class="brush:sql">open o_cursor for
          select car_id, company, model, color, hp, price
          from tbl_car
          where car_id = i_id;</pre>
<p>A <em>Package</em> completa ficará assim:</p>
<pre class="brush:sql">create or replace package PAC_CURSOR is
  --Criando o tipo REF CURSOR que será o cursor
  type g_cursor is ref cursor;

  --Procedure que retornará o cursor
  procedure PRO_RETORNA_LISTA_CARROS(
    i_id     in     tbl_car.car_id%type,
    o_cursor in out g_cursor); -- Nosso cursor

end PAC_CURSOR;
/

create or replace package body PAC_CURSOR is
  procedure PRO_RETORNA_LISTA_CARROS(
    i_id     in     tbl_car.car_id%type,
    o_cursor in out g_cursor) is

       begin
        --Abrindo o cursor para retornar os valores
        open o_cursor for
          select car_id, company, model, color, hp, price
          from tbl_car
          where car_id = i_id;

  end PRO_RETORNA_LISTA_CARROS;

end PAC_CURSOR;</pre>
<p>Temos o lado do Oracle pronto, agora precisamos tratar a chamada no Java.</p>
<p>Como o cursor está sendo retornado por uma <em>procedure</em>, usaremos um <em>java.sql.CallableStatement</em>.</p>
<pre class="brush:java">CallableStatement cs = conn.prepareCall("{call PAC_CURSOR.PRO_RETORNA_LISTA_CARROS(?,?)}");</pre>
<p>O <em>registerOutParameter</em> receberá o tipo <em>oracle.jdbc.OracleTypes.CURSOR</em> e retornará um <em>java.sql.ResultSet</em>. Iteraremos o ResultSet do mesmo modo que iteramos um Iterator.<br />
Cada coluna retornada pelo <em>SELECT</em> será representado como um mapa, usando o <em>getter</em> correpondente. Por exemplo, chamaremos o método <em>getString(&lt;nome coluna&gt;)</em> quando retornar um <em>varchar</em>, <em>getDate(&lt;nome coluna&gt;)</em> quando retornar um <em>date</em> e etc.</p>
<p>O código completo fica assim:</p>
<pre class="brush:java">//Chamando o procedure
CallableStatement cs = conn.prepareCall("{call PAC_CURSOR.PRO_RETORNA_LISTA_CARROS(?,?)}");

//Definindo o tipo do retorno, no caso o cursor
cs.registerOutParameter("o_cursor", OracleTypes.CURSOR);
cs.setLong("i_id", id);

cs.execute();//Executando a chamada

//Recuperando o cursor como um Resultset
ResultSet rs = (ResultSet)cs.getObject("o_cursor");

//Iterando as linhas retornadas
while(rs.next()){
	//Obtendo o valor das colunas
	System.out.println("ID: " + rs.getLong("car_id"));
	System.out.println("Marca: " + rs.getString("company"));
	System.out.println("Modelo: " + rs.getString("model"));
	System.out.println("Cor: " + rs.getString("color"));
	System.out.println("HP: " + rs.getString("hp"));
	System.out.println("Preco: " + rs.getFloat("price"));
}</pre>
<p>No final você conseguirá obter qualquer valor retornado em um <em>SELECT</em>.</p>
<p>Até a próxima!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.andrels.com/wp-pt_BR/index.php/2010/01/recuperando-cursor-de-uma-procedure-do-oracle-no-java/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Recuperando coleção de objetos de uma procedure Oracle</title>
		<link>http://www.andrels.com/wp-pt_BR/index.php/2009/09/recuperando-colecao-de-objetos-de-uma-procedure-oracle/#utm_source=feed&#038;utm_medium=feed&#038;utm_campaign=feed</link>
		<comments>http://www.andrels.com/wp-pt_BR/index.php/2009/09/recuperando-colecao-de-objetos-de-uma-procedure-oracle/#comments</comments>
		<pubDate>Mon, 21 Sep 2009 19:06:53 +0000</pubDate>
		<dc:creator>André</dc:creator>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Tutoriais]]></category>
		<category><![CDATA[collection]]></category>
		<category><![CDATA[jdbc]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://www.andrels.com/wp-pt_BR/?p=109</guid>
		<description><![CDATA[Como prometido há muito tempo atrás (e bota tempo nisso) no tópico &#8220;Passando Objetos Java para uma Procedure do Oracle&#8220;,<a href="http://www.andrels.com/wp-pt_BR/index.php/2009/09/recuperando-colecao-de-objetos-de-uma-procedure-oracle/" class="searchmore">Read the Rest...</a><div class="clr"></div>]]></description>
			<content:encoded><![CDATA[<p>Como prometido há muito tempo atrás (e bota tempo nisso) no tópico &#8220;<a href="http://www.andrels.com/wp-pt_BR/index.php/2009/05/passando-objetos-java-para-uma-procedure-do-oracle/#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed" target="_self">Passando Objetos Java para uma Procedure do Oracle</a>&#8220;, mostrarei como recuperar objetos <a href="http://java.sun.com/" target="_blank">Java</a> contendo uma coleção de outro objetos através de uma procedure do <a href="http://www.oracle.com/">Oracle</a>. Para quem não leu, é altamente recomendado ler o <a href="http://www.andrels.com/wp-pt_BR/index.php/2009/05/passando-objetos-java-para-uma-procedure-do-oracle/#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed" target="_self">post anterior</a>.</p>
<p>Para este tutorial, precisamos incluir a tabela TBL_CLASS e adicionar sua <em>primary key</em> como <em>foreign key</em> na TBL_USER.</p>
<pre class="brush:sql">--num class será a PK e o desc_class será a descrição
create table TBL_CLASS (num_class number, desc_class varchar(100));
alter table TBL_CLASS add primary key(num_class);

alter table TBL_USER add num_class number;
alter table TBL_USER add constraint FK_CLASS foreign key(num_class) references tbl_class(num_class);</pre>
<p>Agora precisamos incluir os novos tipos:</p>
<pre class="brush:sql">create or replace type class_type as object (num_class number, desc_class varchar2(100), users arr_users);
/
create or replace type arr_class as table of class_type;
/</pre>
<p>O tipo <em>class_type</em> será o objeto. Repare que na sua assinatura incluímos o tipo <em>arr_users</em>, que será nossa coleção de <em>user_type</em> (vide <a href="http://www.andrels.com/wp-pt_BR/index.php/2009/05/passando-objetos-java-para-uma-procedure-do-oracle/#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed" target="_self">post anterior</a>), o tipo <em>arr_class</em> será uma coleção de <em>class_type</em>.</p>
<p>Agora incluiremos a <em>procedure</em> responsável por retornar nossa coleção de <em>class_type</em>.</p>
<pre class="brush:sql">procedure pro_select_class(clas in class_type, class_return in out arr_class)is
  class_ref_cur ref_cur;
  --Coleção de classes
  classes arr_class := arr_class();

  begin
    open class_ref_cur for
      select cast(
                multiset(
                  select num_class,
                         desc_class,
                         (select cast(
                                  multiset(
                                    select user_name,
                                           height,
                                           b_date
                                    from tbl_user
                                    --Fazendo o JOIN com a TBL_USER
                                    where tbl_user.num_class = tbl_class.num_class
                                  ) as arr_users)
                          from dual) users
                  from tbl_class
                  --Usando o atributo num_class do parâmetro de entrada
                  where num_class = clas.num_class) as arr_class
      ) classes
    from dual;

    --incluindo ao retorno no array
    fetch class_ref_cur into classes;
    --passando o array para a variável out
    class_return := classes;
end pro_select_class;</pre>
<p>Repare que a <em>procedure</em> recebe o tipo <em>class_type</em> como parâmetro <em>in</em> e retorna o tipo <em>arr_class</em>.</p>
<p>Separando trecho responsável por resgatar e montar nossos objetos teremos:</p>
<pre class="brush:sql">
--Montará a coleção de retorno
select cast(
        multiset(

          --Retornará os objetos class_type e seus atributos
          select num_class,
                 desc_class,

                 --Populará a coleção com user_type
                 (select cast(
                          multiset(
                            select user_name,
                                   height,
                                   b_date
                            from tbl_user
                            where tbl_user.num_class = tbl_class.num_class
                          ) as arr_users)

                  from dual) users

          from tbl_class
          where num_class = clas.num_class) as arr_class
) classes
from dual;
</pre>
<p>Os objetos de banco estão prontos, agora para o Java!</p>
<p>Criaremos o objeto que será interpretado pelo Oracle. Vamos chamá-lo de TypeClass:</p>
<pre class="brush:java">
public class TypeClass implements SQLData{
	public static final String ORACLE_OBJECT_NAME = "CLASS_TYPE"; //Nome do tipo no Oracle
	public static final String ORACLE_CLASS_ARRAY_NAME = "ARR_CLASS"; //Nome do array no Oracle

        //campos criados na tabela TBL_CLASS
	private Long number;
	private String desc;
	private Array users; //Esta será a coleção de user_type (ou TypeUser no Java)

	public String getSQLTypeName() throws SQLException {
		return ORACLE_OBJECT_NAME;
	}

	public void readSQL(SQLInput stream, String typeName) throws SQLException {
		setNumber(stream.readLong());
		setDesc(stream.readString());
		setUsers(stream.readArray());//Usado pelo JDBC driver para ler a coleção
	}

	public void writeSQL(SQLOutput stream) throws SQLException {
		stream.writeLong(getNumber());
		stream.writeString(getDesc());
		stream.writeArray(getUsers());//Usado pelo JDBC driver para armazenar a coleção
	}
	//Getters e setters omitidos
}
</pre>
<p>Precisamos mapear os dois tipos já que ambos serão interpretados na requisição, desta forma:</p>
<pre class="brush:java">
Map<String, Class<?>> typeMaps = connection.getTypeMap();
typeMaps.put(TypeUser.ORACLE_OBJECT_NAME, TypeUser.class);
typeMaps.put(TypeClass.ORACLE_OBJECT_NAME, TypeClass.class);
</pre>
<p>Também precisaremos mapear os dois <em>arrays</em>:</p>
<pre class="brush:java">
typeMaps.put(TypeClass.ORACLE_CLASS_ARRAY_NAME, TypeClass[].class);//retornado pela procedure
typeMaps.put(TypeUser.ORACLE_USER_ARRAY_NAME, TypeUser[].class);//retornado pela coleção de class_type
</pre>
<p>Para a requisição faremos:</p>
<pre class="brush:java">
cs = conn.prepareCall("{call PAC_BEAN.PRO_SELECT_CLASS(?,?)}");
//registrando o tipo de saída, que será um array de TypeClass
cs.registerOutParameter("class_return", OracleTypes.ARRAY, TypeClass.ORACLE_CLASS_ARRAY_NAME);

//passando o objeto de parâmetros da query
cs.setObject("clas", classQry);

cs.execute();
//recuperando e iterando o array de TypeClass
Object[] array = (Object[])cs.getArray("class_return").getArray();

for(Object obj : array){
	TypeClass objClass = ((TypeClass)obj);

	System.out.println("Description: "+objClass.getDesc());

        //Aqui pegamos a coleção (ou array) de user_type(TypeUser) retornada pela query.
	Object[] userArray = (Object[])objClass.getUsers().getArray();
	for(Object user : userArray){
		System.out.println("\tName: " + ((TypeUser)user).getName());
		System.out.println("\tHeight: " + ((TypeUser)user).getHeight());
		System.out.println("\tBirth: " + sdf.format(((TypeUser)user).getBirth())+ "\r\n");
	}
}
</pre>
<p>O final você terá um TypeClass que contém um <a href="http://www.j2ee.me/j2se/1.4.2/docs/api/java/sql/class-use/Array.html" target="_blank">java.sql.Array</a> de TypeUser no atributo getUsers().</p>
<p>E aqui cumpro minha promessa. Baixe o código fonte com o exemplo contendo este e o post anterior <a href="http://www.andrels.com/wp-pt_BR/wp-content/plugins/download-monitor/download.php?id=3" title="clicado 186 vezes">aqui</a>.</p>
<p>Até a próxima!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.andrels.com/wp-pt_BR/index.php/2009/09/recuperando-colecao-de-objetos-de-uma-procedure-oracle/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Passando Objetos Java para uma procedure do Oracle</title>
		<link>http://www.andrels.com/wp-pt_BR/index.php/2009/05/passando-objetos-java-para-uma-procedure-do-oracle/#utm_source=feed&#038;utm_medium=feed&#038;utm_campaign=feed</link>
		<comments>http://www.andrels.com/wp-pt_BR/index.php/2009/05/passando-objetos-java-para-uma-procedure-do-oracle/#comments</comments>
		<pubDate>Sun, 31 May 2009 20:00:18 +0000</pubDate>
		<dc:creator>André</dc:creator>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[jdbc]]></category>

		<guid isPermaLink="false">http://www.andrels.com/wp-pt_BR/?p=31</guid>
		<description><![CDATA[Na empresa onde trabalho houve uma discussão sobre a possibilidade de passar um objeto Java para dentro de uma procedure<a href="http://www.andrels.com/wp-pt_BR/index.php/2009/05/passando-objetos-java-para-uma-procedure-do-oracle/" class="searchmore">Read the Rest...</a><div class="clr"></div>]]></description>
			<content:encoded><![CDATA[<p>Na empresa onde trabalho houve uma discussão sobre a possibilidade de passar um objeto <a href="http://java.sun.com/" target="_blank">Java</a> para dentro de uma <em>procedure </em>ou <em>function </em>do <a href="http://www.oracle.com" target="_blank">Oracle</a>, então resolvi pesquisar e aqui está uma forma bem simples de atingir este objetivo.</p>
<p><em>Este tutorial só funciona com a versão 9i do Oracle, ou superior, e usando o driver JDBC </em><em>ojdbc14g, ou superior.</em></p>
<p>Primeiro precisaremos criar as tabelas, objetos  e procedures. Lembrando que os tipos <em>tbl_users</em> e <em>user_type</em> deverão ser declarados como globais para funcionar, ou seja, fora de <em>packages</em>:</p>
<pre class="brush: sql">-- Criando a tabela
create table tbl_user(user_name varchar2(100), height number, b_date date);
/
--Criando o tipo user_type (nosso bean)
create or replace type user_type as object (user_name varchar2(100), height number, birth_date date);
/
--Criando o tipo arr_users, que é do tipo table of user_type (array de user_type)
create or replace type arr_users as table of user_type;
/</pre>
<p>Criando o <em>spec </em>e <em>body </em>da <em>package </em>que conterá as <em>procedures</em></p>
<pre class="brush: sql">--Spec
create or replace package PAC_BEAN is
  -- REF CURSOR deve ser declarado dentro da package
  type ref_cur is ref cursor;

  -- Procedure usada para o insert
  procedure pro_insert_user(usu in user_type);

  -- Procedure usada para o select
  procedure pro_select_user(usu in user_type, user_return in out arr_users);
end PAC_BEAN;
/</pre>
<pre class="brush: sql">--Body
create or replace package body PAC_BEAN is
  --A procedure de insert receberá o tipo user_type (nosso bean)
  --e o cadastrará na tabela tbl_user
  procedure pro_insert_user(usu in user_type) is
    begin
      insert into tbl_user (user_name, height, b_date)
      values (usu.user_name, usu.height, usu.birth_date);

      commit;
    exception
      when others then
        rollback;
  end pro_insert_user;

  --Procedure de select que receberá um user_type com a informação do nome
  --(cláusula where) e retornará o array arr_users (array de user_type)
  procedure pro_select_user(usu in user_type, user_return in out arr_users)is
    user_ref_cur ref_cur;

    --Instanciando o array
    users arr_users := arr_users();

    begin
      --Abrindo o cursor que retornará nosso array
      open user_ref_cur for
        select cast(
                 multiset(
                   select user_name,
                          height,
                          b_date
                   from tbl_user
                   where user_name like '%'||usu.user_name||'%'
                 ) as arr_users
              ) arr
        from dual;

      --Jogando o retorno do cursor dentro da instância de arr_users
      fetch user_ref_cur into users;

      --Retornando a instância através da variável OUT
      user_return := users;
  end pro_select_user;
end PAC_BEAN;
/</pre>
<p><em>Consulte sobre o funcionamento do <a href="http://download.oracle.com/docs/cd/B14117_01/server.101/b10759/functions015.htm#sthref1120" target="_blank">CAST</a> e <a href="http://download.oracle.com/docs/cd/B14117_01/server.101/b10759/operators006.htm" target="_blank">MULTISET</a>.</em></p>
<p>Construído os objetos de banco precisamos prepara o JavaBean. Ele será uma implementação de <em>java.sql.SQLData</em>, por isso será necessário implementar os métodos:</p>
<p><em>getSQLTypeName()</em> &#8211; É o <em>getter</em> usado para obter o nome do tipo.</p>
<p><em>readSQL(SQLInput, String)</em> &#8211; Usado para converter o objeto SQL em objeto Java.</p>
<p><em>writeSQL(SQLOutput stream)</em> &#8211; Usado para montar o objeto SQL, usado pelo <em>Driver </em>JDBC.</p>
<pre class="brush: java">public class TypeUser implements SQLData{
	//O nome do tipo declarado no Oracle
	public static final String ORACLE_OBJECT_NAME = "USER_TYPE";
	//O nome do array declarado no Oracle
	public static final String ORACLE_USER_ARRAY_NAME = "ARR_USERS";

	//Os atributos
	private String name;
	private Float height;
	private Date birth;

	public TypeUser() {
		height = 0F;
	}
	//Getter retorna o nome do tipo ao JDBC
	public String getSQLTypeName() throws SQLException {
		return ORACLE_OBJECT_NAME;
	}

	public void readSQL(SQLInput stream, String typeName) throws SQLException {
		setName(stream.readString());
		setHeight(stream.readFloat());
		setBirth(stream.readDate());
	}

	public void writeSQL(SQLOutput stream) throws SQLException {
		stream.writeString(getName());
		stream.writeFloat(getHeight());
		stream.writeDate(getBirth() != null ?
				new java.sql.Date(getBirth().getTime()) : null);
	}

        //getters e setters omitidos
}</pre>
<p>Para definir que um tipo poderá ser enviado à procedure é necessário adicioná-lo ao mapa de tipos através de <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/sql/Connection.html#getTypeMap()" target="_blank"><em>Connection.getTypeMap()</em></a>. Este método retorna um <em>Map&lt;String,Class&lt;?&gt;&gt;</em>, onde a chave é o nome do tipo e o valor será a classe <em>SQLData </em>implementada, no nosso caso a <em>TypeUser definida</em> acima. Exemplo:</p>
<pre class="brush: java">Map&gt; typeMaps = connection.getTypeMap();
typeMaps.put(TypeUser.ORACLE_OBJECT_NAME, TypeUser.class);</pre>
<p>A conexão ficará desta forma:</p>
<pre class="brush: java">//Fazendo a conexão
Class.forName("oracle.jdbc.driver.OracleDriver");
connection = DriverManager.getConnection("jdbc:oracle:thin:@&lt;host&gt;:&lt;porta&gt;:&lt;bd&gt;","&lt;usuario&gt;","&lt;senha&gt;");

//Mapeando o tipo necessário
Map&lt;String,Class&lt;?&gt;&gt; typeMaps = connection.getTypeMap();
typeMaps.put(TypeUser.ORACLE_OBJECT_NAME, TypeUser.class);</pre>
<p>Agora que temos a nossa conexão podemos fazer o método de <em>insert</em>, que receberá uma instância <em>TypeUser </em>e uma <em>Connection</em>:</p>
<pre class="brush: java">CallableStatement cs = null;
try {
	//chamando a procedure de insert
	cs = conn.prepareCall("{call PAC_BEAN.PRO_INSERT_USER(?)}");

	//definindo a instância de TypeUser como paramêtro "usu" da procedure
	cs.setObject("usu", typeUser);

	cs.execute();
} catch (SQLException e) {
	e.printStackTrace();
}</pre>
<p>Agora que temos o método de insert, partiremos para o método de <em>select</em>. Como este método retorna um <em>array </em>de objetos, é necessário inserir o tipo do array <em>TypeMap </em>da conexão. O nome passado como chave deve ser o nome do tipo do <em>array </em>no Oracle e o valor será a classe do <em>array</em> que esperamos, desta forma:</p>
<pre class="brush: java">connection.getTypeMap().put(TypeUser.ORACLE_USER_ARRAY_NAME, TypeUser[].class);</pre>
<p>Para a chamada da <em>procedure </em>e <em>registerOutParameter:</em></p>
<pre class="brush: java">cs = conn.prepareCall("{call PAC_BEAN.PRO_SELECT_USER(?,?)}");
cs.registerOutParameter("user_return", OracleTypes.ARRAY, TypeUser.ORACLE_USER_ARRAY_NAME);
cs.setObject("usu", typeUserQry);

cs.execute();</pre>
<p>O método para recuperar o <em>array</em> deverá ser chamado desta forma:</p>
<pre class="brush: java">//user_return é o nome da variável OUT da procedure
Object[] array = (Object[])cs.getArray("user_return").getArray();</pre>
<p>Se até aqui deu tudo certo fique contente, para resgatar os valores do <em>array</em> é só iterá-lo e fazer <em>cast</em> para a classe TypeUser.</p>
<pre class="brush: java">for(Object obj : array){
	System.out.println("Nome: " + ((TypeUser)obj).getName());
	System.out.println("Altura: " + ((TypeUser)obj).getHeight());
	System.out.println("Data de Nascimento: " + sdf.format(((TypeUser)obj).getBirth()));
}</pre>
<p>Desta forma poderemos passar e resgatar objetos simples de uma procedure/function do Oracle.</p>
<p>Próximo passo: <a href="http://www.andrels.com/wp-pt_BR/index.php/2009/09/recuperando-colecao-de-objetos-de-uma-procedure-oracle/#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed">Recuperando coleção de objetos de uma procedure Oracle</a>.</p>
<p>Até lá!</p>
<p>Baixe o código fonte deste tutorial e da <a href="http://www.andrels.com/wp-pt_BR/index.php/2009/09/recuperando-colecao-de-objetos-de-uma-procedure-oracle/#utm_source=feed&amp;utm_medium=feed&amp;utm_campaign=feed">segunda parte</a> <a href="http://www.andrels.com/wp-pt_BR/wp-content/plugins/download-monitor/download.php?id=3" title="clicado 186 vezes">aqui</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.andrels.com/wp-pt_BR/index.php/2009/05/passando-objetos-java-para-uma-procedure-do-oracle/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>

