Baixar Aulas 07 e 08

Transcrição

Baixar Aulas 07 e 08
Programação para Internet II
Aulas 07 e 08
Fernando F. Costa
professor.fimes.edu.br/fernando
[email protected]
Como tratar de grandes conjuntos de
resultados
Quando temos uma grande quantidade de registros a ser
exibida para um usuário, provavelmente não vamos querer
que todos eles sejam carregados e exibidos de uma única
vez.
Uma alternativa seria filtrar a consulta para reduzir os dados a
serem exibidos. Contudo paginar os resultados em pequenas
quantidades também pode ser uma boa solução.
A interface RowSet
Uma boa alternativa para trabalhar com a paginação de
resultados é fazer uso da interface RowSet que foi introduzida
na especificação JDBC 2.0 para definir um meio padrão para
acessar dados armazenados em cache através de um
componente JavaBeans ou através de sistemas distribuídos.
O Bean CachedRowSet
Portanto, para tratar consultas que são maiores que uma tela
inteira e não tão grande para serem verdadeiras devoradoras
de memória, o Bean CachedRowSet se mostra como boa
opção. Ele faz parte da interface RowSet contida na
implementação JDBC 2.0 fornecida pela Sun.
O Bean CachedRowSet
Diferente de ResultSet, CachedRowSet é uma conexão offline
que armazena em cache todas as linhas de sua consulta no
objeto. Nenhuma conexão ativa é necessária porque todos os
dados foram pegos do banco de dados. Para fazer uso deste
Bean, basta configurar suas propriedades de acesso ao
Banco, sua consulta SQL e pronto. A partir deste ponto é só
navegar pelos resultados obtidos.
Exemplo Prático
Vejamos como trabalhar com a paginação de resultados em
JSP utilizando o Bean CachedRowSet. Para isto, crie um novo
projeto web chamado Conferencia.
No MySQL crie uma base de dados chamada conf para
ilustrar nosso exemplo.
Exemplo Prático
No MySQL, digite os seguintes comandos para criar o banco e
as tabelas.
create database conf;
create table conference(
id integer not null auto_increment,
cidade varchar(80),
aeroporto char(3),
assentos integer,
primary key (id)
);
create table shuttles(
id integer not null auto_increment,
aeroporto char(3),
hora time,
assentos integer,
primary key (id)
);
Exemplo Prático
Digite os seguintes comandos para preencher as tabelas criadas:
INSERT
45);
INSERT
'LAX',
INSERT
0);
INSERT
11);
INSERT
0);
INSERT
'SFO',
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INSERT
INTO conference (cidade, aeroporto, assentos) VALUES ('Austin', 'AUS',
INTO conference (cidade, aeroporto, assentos) VALUES ('Las Angeles',
37);
INTO conference (cidade, aeroporto, assentos) VALUES ('New York', 'JFK',
INTO conference (cidade, aeroporto, assentos) VALUES ('Houston', 'IAH',
INTO conference (cidade, aeroporto, assentos) VALUES ('Boston', 'BOS',
INTO conference (cidade, aeroporto, assentos) VALUES ('San Francisco',
12);
INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO
INTO
shuttles
shuttles
shuttles
shuttles
shuttles
shuttles
shuttles
shuttles
shuttles
(aeroporto,
(aeroporto,
(aeroporto,
(aeroporto,
(aeroporto,
(aeroporto,
(aeroporto,
(aeroporto,
(aeroporto,
hora,
hora,
hora,
hora,
hora,
hora,
hora,
hora,
hora,
assentos)
assentos)
assentos)
assentos)
assentos)
assentos)
assentos)
assentos)
assentos)
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
VALUES
('AUS',
('AUS',
('AUS',
('LAX',
('LAX',
('IAH',
('JFK',
('BOS',
('SFO',
'9:40', 10);
'12:00', 12);
'14:15', 0);
'12:15', 10);
'16:35', 10);
'9:30', 0);
'12:15', 10);
'16:35', 10);
'9:30', 10);
Exemplo Prático
Concluído a parte de criação e preenchimento do banco, é
hora de criarmos nosso arquivo JSP que fará a paginação
dos resultados obtidos.
No exemplo a seguir, os resultados serão paginados de 5
em 5 registros. Você pode definir a quantidade que desejar,
basta definir no loop quantos registros serão exibidos por
vez.
Exemplo Prático
CachedResults.jsp (parte 1/3)
<%@page import="java.sql.*" %>
<%@page import="javax.sql.*" %>
<%@page import="com.sun.rowset.*" %>
<jsp:useBean id="crs" class="com.sun.rowset.CachedRowSetImpl"
scope="session">
<% try { Class.forName("com.mysql.jdbc.Driver"); }
catch (ClassNotFoundException e) {
System.err.println("Error" + e);
}
%>
<jsp:setProperty name="crs" property="url"
value="jdbc:mysql://localhost:3306/conf" />
<jsp:setProperty name="crs" property="username" value="root" />
<jsp:setProperty name="crs" property="password" value="adminadmin"
/>
<jsp:setProperty name="crs" property="command" value="select *
from shuttles order by id" />
<% try { crs.execute(); }
catch (SQLException e) { out.println("SQL Error: " + e); }
%>
</jsp:useBean>
Exemplo Prático
<html>
CachedResults.jsp (parte 2/3)
<body>
<center>
<h2>Resultados da Consulta em Cache</h2>
<P>
<table border="2">
<tr bgcolor="tan">
<th>ID</th><th>Aeroporto</th><th>Hora
de
Partida
</th><th>Assentos</th></tr>
<% try {
if ("first".equals(request.getParameter("action")))
crs.beforeFirst();
for (int i=0; (i < 5) && crs.next(); i++) {
%>
<tr>
<td><%= crs.getString("id") %></td>
<td><%= crs.getString("aeroporto") %></td>
<td><%= crs.getString("hora") %></td>
<td><%= crs.getString("assentos") %></td>
</tr>
<% } %>
</table>
Exemplo Prático
CachedResults.jsp (parte 3/3)
<br>
<% if (crs.isAfterLast()) {
crs.beforeFirst(); %>
Fim dos registros<br><br>
<% } }
catch (SQLException e) { out.println("SQL Error" + e); }
%>
<a href="<%= HttpUtils.getRequestURL(request) %>?action=first">
[In&iacute;cio]</a>&nbsp;
<a href="<%= HttpUtils.getRequestURL(request) %>?action=next">
[Pr&oacute;ximo]</a>&nbsp;
</center>
</body>
</html>
Resultado Esperado
Trabalho em Grupo (3 pessoas)
Valor: 2,0 pontos
Data apresentação: 11/04/2011
Descrição: Utilizando os conceitos já apresentados, e enfatizando o conceito de Beans e
Rowset, crie uma aplicação web para fazer o controle de produtos de uma empresa.
A aplicação web deve conter uma parte administrativa na qual deverá ser possível:
●
Cadastrar, Alterar e Remover um produto
Na parte de usuário, deve existir apenas uma lista dos produtos cadastrados com as respectivas
informações:
●
Nome (String)
●
Preço (Double)
●
Quantidade (Integer)
Quando o usuário clicar em comprar um produto, ele deve informar a quantidade. Após confirmar
a quantidade, a aplicação deve remover esta quantidade do estoque.
Observações:
●
A área administrativa só pode ser acessada mediante login.
●
Não deve ser permitido a compra de uma quantidade superior a quantidade em estoque.
●
Se um produto estiver esgotado (quantidade = 0) deve aparecer a mensagem esgotado no
local do preço e não deve ser mostrado o botão Comprar.
Como manter conexões persistentes
A conexão com o BD normalmente é a parte mais lenta de
uma aplicação web. Contudo, manter várias conexões em
aberto pode ser inviável, uma vez que o banco de dados pode
suportar uma quantidade limitada de conexões.
Desta forma, uma boa alternativa para solucionar este
impasse é fazer uso dos Pools de Conexões que são
implementados pelo driver do banco de dados, ou por classes
de Pool de Conexões.
Pool de Conexões
Os pools de conexões mantêm um número fixo de conexões
ativas e as empresta quando solicitado pelas suas páginas
JSP ou Beans.
Logo se tornam uma boa alternativa entre ter muitas conexões
abertas e pagar o preço por conexões e desconexões
frequentes.
Pool de Conexões
A seguir veremos o código que cria um Bean responsável por
encapsular uma conexão de banco de dados. Isto permite
isolar nossas páginas JSP dos detalhes de conexão com o
BD, assim como permite manter nossa conexão através de
diversas páginas ao armazená-la na sessão. Desta maneira
não precisamos sempre nos reconectar no banco de dados.
ConnectionBean
public class ConnectionBean implements HttpSessionBindingListener {
private Connection connection;
private Statement statement;
private static final String driver="com.mysql.jdbc.Driver";
private
static
final
String
dbURL="jdbc:mysql://localhost:3306/conf";
private static final String login="root";
private static final String password="adminadmin";
public ConnectionBean() {
}
try {
Class.forName(driver);
connection=DriverManager.getConnection(dbURL,login,password);
statement=connection.createStatement();
}
catch (ClassNotFoundException e) {
System.err.println("ConnectionBean: driver unavailable");
connection = null;
}
catch (SQLException e) {
System.err.println("ConnectionBean: driver not loaded");
connection = null;
}
ConnectionBean
public void valueBound(HttpSessionBindingEvent event) {
System.err.println("ConnectionBean: in the valueBound method");
try {
if (connection == null || connection.isClosed()) {
connection =
DriverManager.getConnection(dbURL,login,password);
statement = connection.createStatement();
}
}
catch (SQLException e) { connection = null; }
}
public void valueUnbound(HttpSessionBindingEvent event) {
try {
connection.close();
}
catch (SQLException e) { }
finally {
connection = null;
}
}
}
protected void finalize() {
try {
connection.close();
}
catch (SQLException e) { }
}
Processamento de Transações
As operações efetuadas em um BD nem sempre são
atômicas, ou seja, na maioria das vezes ela envolve duas ou
mais operações que precisam acontecer com sucesso para
garantir a integridade do banco de dados. Ex: transação
bancária.
Processamento de Transações
Os Bancos de Dados fornecem um mecanismo conhecido
como transações para tratar deste assunto. Em JSP devemos
efetuar um commit() no objeto Connection para concluir uma
operação que ocorreu sem erros, ou efetuar um rollback() do
objeto Connection para retornar o banco ao estado em que ele
se encontrava no inicio da transação.
Processamento de Transações
Como padrão o JDBC assume que cada instrução SQL é uma
transação, e portanto, efetua um autocommit a cada instrução
que
é
emitida.
Para
que
esse
controle
seja
feito
“manualmente”, devemos desativar o recurso autocommit. A
seguir temos um exemplo desta situação em uma operação
de transação bancária entre as contas de Bob e Sue.
Desativando o recurso autocommit
Observação:
Lembrem-se de reativar o recurso autocommit ao concluírem suas transações.
connection.setAutoCommit(false);
try {
Statement st = connection.createStatement();
st.executeUpdate(
"UPDATE ACCTS SET BALANCE=(BALANCE-100) WHERE OWNER = "Bob");
st.executeUpdate(
"UPDATE ACCTS SET BALANCE=(BALANCE + 100) WHERE OWNER = "Sue");
connection.commit();
}
catch (SQLException e) {
connection.rollback();
}
finally {
connection.setAutoCommit(true);
}
Exemplo Prático
A seguir criaremos um exemplo para trabalhar com os
assuntos tratados na aula de hoje. O objetivo do exemplo que
será criado é permitir que sejam feitas reservas de vagas em
conferências de computação que ocorrerão em todo o mundo.
Contudo, o sistema deve garantir que além de reservar uma
vaga na conferência, também seja possível reservar uma vaga
na ponte aérea com destino a conferência selecionada.
Exemplo Prático
Neste exemplo utilizaremos o projeto Conferencia criado
anteriormente, juntamente com a base de dados conf que foi
criada.
Exemplo Prático
import java.sql.*;
import javax.servlet.http.*;
ConnectionBean.java (parte 1 de 3)
public class ConnectionBean implements HttpSessionBindingListener {
private Connection connection;
private Statement statement;
private static final String driver="com.mysql.jdbc.Driver";
private
static
final
String
dbURL="jdbc:mysql://localhost:3307/conf";
private static final String login="root";
private static final String password="adminadmin";
public ConnectionBean() {
try {
Class.forName(driver);
connection=DriverManager.getConnection(dbURL,login,password);
statement=connection.createStatement();
}
catch (ClassNotFoundException e) {
System.err.println("ConnectionBean: driver unavailable");
connection = null;
}
catch (SQLException e) {
System.err.println("ConnectionBean: driver not loaded");
connection = null;
}
}
Exemplo Prático
ConnectionBean.java (parte 2 de 3)
public Connection getConnection() {
return connection;
}
public void commit() throws SQLException {
connection.commit();
}
public void rollback() throws SQLException {
connection.rollback();
}
public void setAutoCommit(boolean autoCommit)
throws SQLException {
connection.setAutoCommit(autoCommit );
}
public void valueBound(HttpSessionBindingEvent event) {
System.err.println("ConnectionBean: in the valueBound method");
try {
if (connection == null || connection.isClosed()) {
connection =
DriverManager.getConnection(dbURL,login,password);
statement = connection.createStatement();
}
}
catch (SQLException e) { connection = null; }
}
Exemplo Prático
ConnectionBean.java (parte 3 de 3)
public ResultSet executeQuery(String sql) throws SQLException {
return statement.executeQuery(sql);
}
public int executeUpdate(String sql) throws SQLException {
return statement.executeUpdate(sql);
}
public void valueUnbound(HttpSessionBindingEvent event) {
try {
connection.close();
}
catch (SQLException e) { }
finally {
connection = null;
}
}
}
protected void finalize() {
try {
connection.close();
}
catch (SQLException e) { }
}
Exemplo Prático
index.jsp
<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;
charset=UTF-8">
<title>JSP Page</title>
</head>
<body>
<center>
<h1>Confer&ecirc;ncia Mundial de
Computa&ccedil;&atilde;o</h1>
<a href="CachedResults.jsp" target="_self">Vagas
Disponíveis</a><br><br>
<a href="conference.jsp" target="_self">Fazer minha
inscri&ccedil;&atilde;o</a>
</center>
</body>
</html>
Exemplo Prático
conference.jsp (parte 1 de 2)
<%@page import="java.sql.*" errorPage="error.jsp" %>
<jsp:useBean id="connection"
class="com.taglib.wdjsp.databases.ConnectionBean" scope="session"/>
<html>
<body>
<center>
<font size="+2" face="arial"><b>Confer&ecirc;ncia Registros</b></font>
<form action="shuttle.jsp" method="post">
<table border=1 bgcolor="tan" width="50%" align="center">
<tr>
<td>
<table border="0" bgcolor="white" cellspacing=0 width="100%">
<tr bgcolor="tan">
<th>&nbsp;</th><th>Cidade</th><th>Vagas Restantes</th></tr>
<tr><% String sql = "select * from conference";
ResultSet results = connection.executeQuery(sql);
while (results.next()) {
if (results.getInt("assentos") > 0) {
%>
<td>
<input type="radio" name="show" value="<%=
results.getString("id") %>">
</td> <% }
Exemplo Prático
conference.jsp (parte 2 de 2)
else { %>
<td>&nbsp;</td>
<% } %>
<td><%= results.getString("cidade") %></td>
<td align="center"><%= results.getString("assentos") %></td>
</tr>
<% } %>
</table>
</td>
</tr>
</table>
<p>
<input type="submit" value="Proximo (Escolher Ponte Aerea)">
</form>
</center>
</body>
</html>
Exemplo Prático
shuttle.jsp (parte 1 de 2)
<%@ page import="java.sql.*" errorPage="error.jsp" %>
<jsp:useBean id="connection"
class="com.taglib.wdjsp.databases.ConnectionBean" scope="session"/>
<%
String showID = request.getParameter("show");
connection.setAutoCommit(false);
String sql;
sql = "UPDATE conference set assentos=assentos-1 where id=" +
showID;
connection.executeUpdate(sql);
%>
<html>
<body>
<center>
<font size="+2" face="arial"><b>Reservar Ponte
A&eacute;rea</b></font>
<form action="confirm.jsp" method="post">
<table border=1 bgcolor="tan" width="50%" align="center">
<tr><td>
<table border="0" bgcolor="white" cellspacing=0 width="100%">
<tr bgcolor="tan"><th>&nbsp;</th>
<th>Aeroporto</th><th>Hora</th><th>Lugares Vagos</th></tr>
Exemplo Prático
shuttle.jsp (parte 2 de 2)
<tr>
<%
sql = "SELECT s.* from shuttles s, conference c where c.id=" +
showID + " and s.aeroporto = c.aeroporto";
ResultSet results = connection.executeQuery(sql);
while (results.next()) {
if (results.getInt("assentos") > 0) {
%>
<td>
<input type="radio" name="shuttle"
value="<%= results.getString("id") %>">
</td>
<% } else { %>
<td>&nbsp;</td>
<% } %>
<td><%= results.getString("aeroporto") %></td>
<td><%= results.getTime("hora") %></td>
<td align="center"><%= results.getString("assentos") %></td>
</tr>
<% } %>
</table>
</td></tr></table>
<input type="hidden" name="show" value="<%= showID %>">
<input type="submit" value="Proximo (Revisar Reservas)">
</form>
</center></body></html>
Exemplo Prático
confirm.jsp (parte 1 de 2)
<%@ page import="java.sql.*" errorPage="error.jsp" %>
<jsp:useBean id="connection"
class="com.taglib.wdjsp.databases.ConnectionBean" scope="session"/>
<%
String sql;
String shuttleID = request.getParameter("shuttle");
String showID = request.getParameter("show");
sql = "UPDATE shuttles set assentos=assentos-1 where id=" +
shuttleID;
connection.executeUpdate(sql);
sql = "SELECT c.cidade, c.aeroporto, s.hora from conference c, " +
"shuttles s where c.id=" + showID + " and s.id=" + shuttleID;
ResultSet results = connection.executeQuery(sql);
results.next();
%>
<html><body><center>
<font size="+2" face="arial"><B>Confirma&ccedil;&atilde;o de
Reservas</b></font>
<form action="finish.jsp" method=post>
<table border=1 bgcolor="tan" width="50%" align="center">
<tr><td>
Exemplo Prático
confirm.jsp (parte 2 de 2)
<table border="0" bgcolor="white" cellspacing=0 width="100%">
<tr bgcolor="tan"><th>Resumo</th></tr>
<tr><td>
Reserva requisitada para a confer&ecirc;ncia na cidade de
<b><%= results.getString("cidade") %></b>,
com ponte a&eacute;rea partindo do aeroporto de
<b><%= results.getString("aeroporto") %></b> &agrave;s
<b><%= results.getTime("hora") %></b>.
<p>
Para confirmar suas reservas, selecione Confirmar Reservas.
</td></tr>
</table>
</td></tr></table>
<p>
<input type="submit" name="commit" value="Confirmar Reservas">
<input type="submit" name="rollback" value="Cancelar Reservas">
</body>
</html>
Exemplo Prático
finish.jsp
<%@ page import="java.sql.*,com.taglib.wdjsp.databases.*"
errorPage="error.jsp" %>
<html><body>
<%
ConnectionBean connection =
(ConnectionBean)session.getAttribute("connection");
if (request.getParameter("commit") != null)
connection.commit();
else
connection.rollback();
session.removeAttribute("connection");
%>
<center>
<% if (request.getParameter("commit") != null) { %>
<font size="+2" face="arial"><b>Confirma&ccedil;&atilde;o de
Reservas</b></font>
<p>
Sua reserva foi confirmada, obrigado...
<% } else { %>
<font size="+2" face="arial"><b>Cancelamento de Reservas</b></font>
<p> Suas reservas foram canceladas.
<% } %>
<a href="conference.jsp">Outra Reserva</a>
</body></html>
Exemplo Prático
error.jsp
<%@ page import="java.sql.*,com.taglib.wdjsp.databases.*"
isErrorPage="true" %>
<html>
<body>
<%
if (exception instanceof SQLException) {
try {
ConnectionBean connection =
(ConnectionBean)session.getAttribute("connection");
connection.getConnection().rollback();
session.removeAttribute("connection");
}
catch (SQLException e) { }
}
%>
<center>
<font size="+2" face="arial"><b>Erro na
Aplica&ccedil;&atilde;</b></font>
<p>
Um erro ocorreu: <tt><%= exception %></tt>
<p>
<a href="conference.jsp">Outra Reserva</a>
</center></body></html>
Boa Noite!

Documentos relacionados

Nova aba

Nova aba Data de Nascimento

Leia mais