Archive for setembro, 2009

Recuperando coleção de objetos de uma procedure Oracle

Como prometido há muito tempo atrás (e bota tempo nisso) no tópico “Passando Objetos Java para uma Procedure do Oracle“, mostrarei como recuperar objetos Java contendo uma coleção de outro objetos através de uma procedure do Oracle. Para quem não leu, é altamente recomendado ler o post anterior.

Para este tutorial, precisamos incluir a tabela TBL_CLASS e adicionar sua primary key como foreign key na TBL_USER.

--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);

Agora precisamos incluir os novos tipos:

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;
/

O tipo class_type será o objeto. Repare que na sua assinatura incluímos o tipo arr_users, que será nossa coleção de user_type (vide post anterior), o tipo arr_class será uma coleção de class_type.

Agora incluiremos a procedure responsável por retornar nossa coleção de class_type.

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;

Repare que a procedure recebe o tipo class_type como parâmetro in e retorna o tipo arr_class.

Separando trecho responsável por resgatar e montar nossos objetos teremos:

--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;

Os objetos de banco estão prontos, agora para o Java!

Criaremos o objeto que será interpretado pelo Oracle. Vamos chamá-lo de TypeClass:

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
}

Precisamos mapear os dois tipos já que ambos serão interpretados na requisição, desta forma:

Map> typeMaps = connection.getTypeMap();
typeMaps.put(TypeUser.ORACLE_OBJECT_NAME, TypeUser.class);
typeMaps.put(TypeClass.ORACLE_OBJECT_NAME, TypeClass.class);

Também precisaremos mapear os dois arrays:

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

Para a requisição faremos:

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");
	}
}

O final você terá um TypeClass que contém um java.sql.Array de TypeUser no atributo getUsers().

E aqui cumpro minha promessa. Baixe o código fonte com o exemplo contendo este e o post anterior aqui.

Até a próxima!


Tirando Screen Shots com Java

Aqui mostrarei como fazer uma classe para tirar Screen shots .

Estava pensando com quão complexo seria fazer uma classe que tirasse screen shots do compulador local e o armazenasse em um arquivo. Perguntando ao tio “G” descobri a classe Robot, que possui o método createScreenCapture.

Agora mostrarei como implementar esta funcionalidade:

Robot robot = new Robot();
//Definindo o retângulo que será a área de captura da tela que, neste caso, será a tela inteira.
Rectangle rect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());

BufferedImage img = robot.createScreenCapture(rect);

Aqui definimos a área de captura e obtivemos um BufferedImage, que já é nossa imagem. Agora é só persisti-la no disco.

//Capturando o ImageWriter e ImageWriterParam
ImageWriter writer = ImageIO.getImageWritersByFormatName("jpeg").next();
ImageWriteParam iwp = writer.getDefaultWriteParam();

//Definindo o modo de compressão e a qualidade
iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
iwp.setCompressionQuality(1);

//Persistindo a imagem
writer.setOutput(new FileImageOutputStream(arquivo));

IIOImage iioimage = new IIOImage(img, null, null);

writer.write(null, iioimage, iwp);
writer.dispose();

Aqui capturamos o ImageWriter e ImageWriterParam para configurar o método de compressão e a qualidade da imagem.

Na linha 07 definimos a qualidade como 1, onde o valor varia de 0 (zero), maior compressão e menor qualidade, até 1 (um), menor compressão e maior qualidade. Em seguida persistimos o arquivo no HD.

Pronto! Simples, não?!.

Faça o download do exemplo aqui.

Até a próxima!

Neste caso será a tela inteira.

  • AdSense

  • Copyright © 1996-2010 André L. S.. All rights reserved.
    iDream theme by Templates Next | Powered by WordPress