SQLJ: uma alternativa de
alto nível a JDBC
Universidade Federal de Campina Grande
Disciplina: Banco de Dados I
Professor: Cláudio de Souza Baptista
Estagiário: Elvis Rodrigues da Silva
http://www.lsi.dsc.ufcg.edu.br/
Roteiro
• Introdução
• Sintaxe Inicial
• Comandos avançados
• Requisitos
• Referências
Introdução (1 de 5)
• SQLJ é uma tecnologia que permite a
um programa Java acessar um banco
de dados utilizando statements SQL
embutidos
• Arquivo fonte termina com “.sqlj”
• Manipulações SQLJ
– Meta informações: Create, Alter, Drop
– Dados: Select, Insert, Update, Open, Fetch
– Controle de Transações: Commit, Rollback
Introdução (2 de 5)
• SQLJ não pode ser compilado
diretamente pelo compilador Java
• Solução: usar um tradutor
– SQLJ Translator
Introdução (3 de 5)
• O tradutor verifica erros de sintaxe e
semânticos na instrução SQL em tempo
de tradução:
– Nomes incorretos
– Checagem de tipos
– Verifica se o comando SQL está de acordo
com o Banco de Dados
– Etc.
Introdução (4 de 5)
• A IDE Oracle JDeveloper reconhece a
sintaxe de SQLJ para o banco de dados
Oracle, mas é possível utilizar outros
compiladores
• O IBM Websphere também possui
compatibilidade com SQLJ para o banco
de dados IBM DB2
Introdução (5 de 5)
• Vantagens de SQLJ sobre JDBC
(comandos estáticos)
– Código-fonte reduzido
– Checagem de tipos SQL via conexão
– Associação de variáveis em um único
comando
– Checagem de tipos de parâmetros e retorno
antes da execução
• Desvantagens
– Um passo a mais no processamento:
tradução de sqlj para java
Sintaxe Inicial: Declarações
(1 de 3)
• Declarações SQLJ :
– #sql{<comando SQL>};
• Regras pra declarações SQLJ
SQLJ declaration;
// OK (top level scope)
class Outer {
SQLJ declaration; // OK (class level scope)
class Inner {
SQLJ declaration; // OK (nested class scope)
}
void func() {
SQLJ declaration; /* OK in JDK 1.2.x; ILLEGAL in JDK
1.1.x (method block)*/
}
}
• Exemplo:
Sintaxe Inicial: Declarações
(3 de 3)
• Existem 2 tipos de declarações SQLJ:
– Iterator
– Context
• Iterator
– Declarações que definem classes iterator
– Usado para receber os resultados de
consultas
• Context
– Usado para criar uma conexão ao Banco de
Dados
Sintaxe Inicial: SQLJ
Namespace
• Todas as restrições de nome em Java
são aplicadas aqui
• Evitar usar as palavras reservadas,
nome de classes e colunas em iterator:
– iterator
– context
– with
Sintaxe Inicial: Iterator (1 de
8)
• Declaração:
• Modifiers:
– publics, static, etc
• Existem 2 tipos de iterator:
– named iterators
– positional iterators
Sintaxe Inicial: Iterator (2 de
8)
• named iterators
• positional iterators
Sintaxe Inicial: Iterator (3 de
8)
• Exemplo named iterators:
#sql iterator MyCheckedIter (String ename, double sal);
...
MyCheckedIter iter;
#sql iter = { SELECT ename, sal FROM Employee};
while (iter.next()) {
System.out.println(iter.ename());
System.out.println(iter.sal());
}
Sintaxe Inicial: Iterator (4 de
8)
• Obtendo os elementos de um Positional
iterators
– FETCH INTO seguido por endFetch()
– O FETCH INTO chama implicitamente o
método next()
• Exemplo de “positional iterators”
Sintaxe Inicial: Iterator (6 de
8)
• Iterator e ResultSet podem existir dentro de
outro Iterator em Oracle SQLJ
• Exemplos:
CREATE TABLE DEPT (
DEPTNO NUMBER(2),
DNAME VARCHAR2(14)
);
CREATE TABLE EMP (
EMPNO NUMBER(4),
ENAME VARCHAR2(10),
SAL NUMBER(7,2),
DEPTNO NUMBER(2)
);
Sintaxe Inicial: Iterator (7 de
8)
Sintaxe Inicial: Iterator (8 de
8)
• Outro exemplo:
• Declaração:
• Execução:
Sintaxe Inicial: Connection
(1 de 7)
• Existem várias formas de criar uma conexão
com o Banco de Dados:
– Criando um contexto Default
DefaultContext defctx = new DefaultContext
("jdbc:oracle:thin:@localhost:1521:orcl", "scott",
"tiger", false);
– Através da declaração SQLJ:
Sintaxe Inicial: Connection
(2 de 7)
• Exemplo:
#sql context MyContext;
...
MyContext myContext = new
MyContext("jdbc:oracle:thin:@localhost:1521:dbhome",
“scott", "tiger ", false);
Sintaxe Inicial: Connection
(3 de 7)
• Simples conexão usando connect() da classe
oracle.sqlj.runtime.Oracle
– Oracle.connect(MyClass.class, "connect.properties");
– Oracle.connect("jdbc:oracle:thin:@localhost:1521:
orcl", "scott", "tiger");
• A função connect() simplifica o processo de
criação e usa uma instância da classe
DefaultContext
Sintaxe Inicial: Connection
(4 de 7)
• Formato do arquivo “properties”:
sqlj.url=jdbc:oracle:thin:@localhost:1521:dbhome
sqlj.user=scott
sqlj.password=tiger
Sintaxe Inicial: Connection
(5 de 7)
• Multiplas conexões
DefaultContext ctx1 = Oracle.getConnection (
"jdbc:oracle:thin:@localhost1:1521:orcl1", "scott",
"tiger");
DefaultContext ctx2 = Oracle.getConnection (
"jdbc:oracle:thin:@localhost2:1521:orcl2", "bill", "lion");
#sql [ctx1] { SQL operation };
...
#sql [ctx2] { SQL operation };
Sintaxe Inicial: Connection
(6 de 7)
• Se uma conexão é usada várias vezes podemos fazer:
DefaultContext.setDefaultContext(ctx1);
#sql { SQL operation };
#sql { SQL operation };
#sql { SQL operation };
...
DefaultContext.setDefaultContext(ctx2);
#sql { SQL operation };
#sql { SQL operation };
#sql { SQL operation };
Sintaxe Inicial: Connection
(7 de 7)
• Fechando a conexão
– Há um “commit” implícito quando a conexão é fechada
...
finally {
try {
ctx.close();
//ou
Oracle.close();
} catch(SQLException ex) {
...
}
}
...
Sintaxe Inicial: Interfaces (1
de 3)
• Iterator e Context são transformados em
classes java depois de traduzidos
#sql iterator MyCheckedIter (String ITEM_NAME, Double COST);
tradutor
class MyCheckedIter extends sqlj.runtime.ref.ResultSetIterImpl
implements sqlj.runtime.NamedIterator{
…
public String ITEM_NAME(){…}
public Double COST(){…}
…
}
Sintaxe Inicial: Interfaces (2
de 3)
• Quando se declara um “iterator” ou
“context”, pode-se especificar uma ou
mais interfaces
#sql <modifiers> context context_classname implements
intfc1,..., intfcN;
• Exemplo:
#sql iterator EmpIter implements mypackage.EmpIterIntfc
(String emame, int empno, float sal);
• Exemplo: evitar acesso a uma coluna da tabela
Erro de
compilação
Sintaxe Inicial: SubClasses
• Exemplo:
// Declarando um iterator
#sql public static iterator EmpIter(int empno, String
ename);
...
//criando a subclasse
public static class EmpColl extends EmpIter {...}
...
//usando a subclasse
EmpColl ec;
#sql ec = { select ename, empno from emp };
Sintaxe Inicial: Hosts (1 de
4)
• Usados para troca de valores entre
variáveis Java e SQLJ
• Podem ser referenciados dentro de uma
instrução SQLJ
• SQLJ fica responsável em devolver os
valores
• O tipo da variável host é convertida
para o tipo compatível com a coluna
Sintaxe Inicial: Hosts (2 de
4)
• Sintaxe:
– : [mode] variavel_host
– Onde mode pode ser
• IN, OUT e INOUT
– O default é OUT se a variável é parte de
uma lista INTO ou em um statement SET e
é IN caso contrário
Sintaxe Inicial: Hosts (3 de
4)
• Exemplos
String nome;
int mat = 5;
#sql {
SELECT aluno INTO :nome
FROM cadastro
WHERE matricula = :mat
}
Sintaxe Inicial: Hosts (4 de
4)
• Outro exemplo:
float balance = 12500.0;
float minPmtRatio = 0.05;
...
#sql { UPDATE creditacct SET minPayment = :(balance *
minPmtRatio) WHERE acctnum = 537845 };
Comandos Avançados:
Scrollable Iterators (1 de 8)
• Iterator tem apenas um único método
para navegar:
– next()
• Scrollable Iterators permite o usuário
dizer o sentido da iteração
Comandos Avançados:
Scrollable Iterators (2 de 8)
• Para um iterator tornar-se um
Scrollable Iterator ele deve implementar
a interface “sqlj.runtime.Scrollable”
• Declaração:
#sql public static MyScrIter implements sqlj.runtime.Scrollable
(String ename, int empno);
Comandos Avançados:
Scrollable Iterators (3 de 8)
• Scrollable Interface:
– setFetchDirection(int)
• FETCH_FORWARD (default)
• FETCH_REVERSE
–
–
–
–
–
getFetchDirection()
boolean isBeforeFirst()
boolean isFirst()
boolean isLast()
boolean isAfterLast()
Comandos Avançados:
Scrollable Iterators (4 de 8)
• Métodos de navegação:
–
–
–
–
–
boolean
boolean
boolean
boolean
boolean
previous()
first()
last()
absolute(int)
relative(int)
– void beforeFirst()
– void afterLast()
Comandos Avançados:
Scrollable Iterators (5 de 8)
• Exemplo
...
Comandos Avançados:
Scrollable Iterators (6 de 8)
• Scrollable Positional Iterators
• O comando:
– #sql { FETCH :iter INTO :x, :y, :z }
É uma abreviação para:
– #sql { FETCH NEXT FROM :iter INTO :x, :y,
:z }
Comandos Avançados:
Scrollable Iterators (7 de 8)
• O comando
– #sql { FETCH NEXT FROM :iter INTO :x, :y, :z }
sugere um padrão para movimentos
alternativos:
–
–
–
–
#sql
#sql
#sql
#sql
:z }
– #sql
}
{
{
{
{
FETCH
FETCH
FETCH
FETCH
PREVIOUS FROM :iter INTO :x, :y, :z }
FIRST FROM :iter INTO :x, :y, :z }
LAST FROM :iter INTO :x, :y, :z }
ABSOLUTE :n FROM :iter INTO :x, :y,
{ FETCH RELATIVE :n FROM :iter INTO :x, :y, :z
Comandos Avançados:
Scrollable Iterators (8 de 8)
• Não podemos usar constantes
numéricas para especificar
movimentos:
– #sql { FETCH RELATIVE 0 FROM :iter INTO
:x, :y, :z }; (ERRADO)
– #sql { FETCH RELATIVE :(0) FROM :iter
INTO :x, :y, :z }; (OK)
Comandos Avançados:
Constantes (1 de 2)
• Declaração com constantes
• As constantes são sempre produzidas
como “public static final”
Comandos Avançados:
Constantes (2 de 2)
• Exemplo:
#sql public iterator MyScrollableIterator implements
sqlj.runtime.Scrollable with (sensitivity=ASENSITIVE) (String ename,
int empno);
• Sensitivity é um atributo da interface
sqlj.runtime.ResultSetIterator
• “with” sempre deve vir após
“implements”
Comandos Avançados:
Transação (1 de 4)
• Uma transação é uma seqüência de
operações SQL que o BD trata como
uma simples unidade
• Uma transação começa depois de:
– conectar ao Banco de Dados
– depois de um COMMIT
– depois de um ROLLBACK
Comandos Avançados:
Transação (2 de 4)
• Commit automático
• Por default o auto-commit tem o valor
“false”
• Ativando o auto-commit:
Oracle.getConnection (
"jdbc:oracle:thin:@localhost:1521:orcl", "scott", "tiger", true);
Comandos Avançados:
Transação (3 de 4)
• Mudando o auto-commit
– ctx.getConnection().setAutoCommit(false);
ou
– ctx.getConnection().setAutoCommit(true);
Comandos Avançados:
Transação (4 de 4)
• Commit e Rollback manual
– #sql { COMMIT }
– #sql { ROLLBACK }
• Não usar o COMMIT ou o ROLLBACK
quando o auto-commit estiver
habilitado
Comandos Avançados: SQL
Dinâmico (1 de 6)
• O Oracle9i possui uma extensão para
suportar SQL dinâmico em SQLJ
– Operações que podem mudar em tempo de
execução
• “Meta bind” são usados para SQL
dinâmico em SQLJ
Comandos Avançados: SQL
Dinâmico (2 de 6)
• Sintaxe
:{ Java_bind_expression }
ou
:{ Java_bind_expression :: SQL_replacement_code }
Identificador ou expressão
Java do tipo String
Seqüência de SQL tokens
Comandos Avançados: SQL
Dinâmico (3 de 6)
•
Exemplo 1:
...
int x = 10;
int y = x + 10;
int z = y + 10;
String table = "new_Emp";
#sql { INSERT INTO :{table :: emp} VALUES (:x, :y, :z) };
...
Durante a tradução:
INSERT INTO emp VALUES (10, 20, 30);
Durante a execução:
INSERT INTO new_Emp VALUES (10, 20, 30);
Comandos Avançados: SQL
Dinâmico (4 de 6)
• Exemplo 2:
...
String table = "new_Emp";
String query = "ename LIKE ’S%’ AND sal>1000";
#sql myIter = { SELECT * FROM :{table :: emp2} WHERE :{query ::
ename=’SCOTT’} };
...
Durante a transação:
SELECT * FROM emp2 WHERE ename=’SCOTT’;
Durante a execução:
SELECT * FROM new_Emp WHERE ename LIKE ’S%’ AND sal>1000;
Comandos Avançados: SQL
Dinâmico (5 de 6)
• Restrições
• O “Meta bind” pode ser usado nos
seguintes tipos de comandos:
–
–
–
–
o nome de uma tabela
o nome de uma coluna (sem alias)
todo ou parte de uma cláusula WHERE
um valor literal ou uma expressão SQL
Comandos Avançados: SQL
Dinâmico (6 de 6)
• Um “Meta bind” não pode ser a primeira
expressão de uma operação SQL
• Não pode conter o token “INTO”
• Não pode aparecer em qualquer dos
tipos de instruções SQL/SQLJ:
– CALL, VALUES, PSM SET, COMMIT,
ROLLBACK, FETCH INTO ou CAST
Requisitos (1 de 2)
• Para rodar um programa SQLJ
precisamos de:
– Um driver JDBC
– Um SQLJ translator:
• [Oracle Home]/sqlj/lib/translator.zip (ou .jar)
– Um SQLJ runtime:
• runtime11.jar, runtime12. jar, runtime. jar,
runtime-nonoracle. jar
– O programa [Oracle Home]/bin/sqlj
Requisitos (2 de 2)
• Procedimentos para rodar um programa SQLJ:
–
–
–
–
Colocar todos os .jar necessários no “classpath”
Editar o “path” para a pasta [Oracle Home]/bin/
Criar o arquivo “.sqlj”
Executar o comando:
• sqlj nome_arq.sqlj
– Executar o programa
• Java nome_arq
Referências
• Manuais da Oracle
– http://www.oracle.com/technology/documentation/in
dex.html
• Tutoriais na Web:
– http://www.onjava.com/pub/ct/46
– http://www.javaworld.com/javaworld/jw-051999/jw-05-sqlj_p.html
– http://www.javaolympus.com/J2SE/Database/SQLJ/
SQLJ.jsp
• Leitura recomendada: Java Programming with
Oracle SQLJ, Jason Price, O’Reilly
Download

SQLJ - Universidade Federal de Campina Grande