Hoje, vamos desenvolver uma biblioteca de classes que mapeia os conceitos do domínio do problema, e faz a ponte entre a interface com o utilizador, cujo desenvolvimento trataremos no próximo artigo, e a camada de persistência de dados, tratada no primeiro artigo desta série.
Esta camada com conceitos e operações do domínio do problema é comummente chamada de camada intermédia ou camada de lógica do negócio.
Podemos considerar que o nosso pequeno sistema aplicacional terá, então, uma arquitectura de software em 3-camadas (abordaremos o tema da arquitectura de software num artigo futuro).
Há várias maneiras de desenvolver esta camada intermédia, a qual pode ela própria conter uma ou mais camadas. Nós iremos desenvolver uma classe para cada conceito do domínio, o que corresponde, mais ou menos, neste pequeno exemplo, a desenvolver uma classe para cada tabela da base de dados.
Há várias maneiras de fazer isso. Em particular, vamos ver duas possíveis maneiras, cada uma com o seu grupo de defensores, e com as suas próprias vantagens e desvantagens.
1 – Há autores que defendem o desenvolvimento de uma camada de classes apenas com atributos, getters e setters (ex.: classe Book abaixo), separadamente de uma camada de classes com operações com significado para o negócio (ex.: classe BookBLL abaixo).
1.1 classe Book:
public class Book {
private int idBook;
private String title;
private String editor;
private java.sql.Date date;
private String ISBN;
private String edition;
//
private List<Author> authors = new ArrayList<Author>();
public Book() { }
public int getID() { return this.idBook; }
public void setTitle(String title) { this.title = title; }
public String getTitle() { return title; }
public void setEditor(String editor) { this.editor = editor; }
public String getEditor() { return editor; }
public void setDate(java.sql.Date date) { this.date = date; }
public java.sql.Date getDate() { return date; }
public void setISBN(String ISBN) { this.ISBN = ISBN; }
public String getISBN() { return ISBN; }
public void setEdition(String edition) { this.edition = edition; }
public String getEdition() { return edition; }
public List<Author> getAuthors() { return this.authors; }
}
1.2 classe BookBLL:
public class BookBLL {
private DBAccessObj dbo;
public BookBLL() {
this.dbo = new DBAccessObj();
this.dbo.openConnection();
}
public BookBLL(DBAccessObj dbo) {
this.dbo = dbo;
this.dbo.openConnection();
}
public void create(Book b) throws SQLException{
String sqlCommand =
"INSERT INTO Book (ISBN, Title, Edition, Editor) VALUES('" +
b.getISBN() + "', '" + b.getTitle() + "', '" +
b. getEdition() + "', '" + b.getEditor() + "')";
this.dbo.executeSQL(sqlCommand);
}
…
// restantes operações
…
}
Esta primeira abordagem não explora o encapsulamento de dados e operações sobre os dados (conceito fundamental do paradigma de programação orientado a objetos).
2 – Outra maneira, é desenvolver:
• uma camada de classes com atributos, getters e setters, mais as operações CRUD (Create, Retrieve, Update, Delete) (ex.: class BookDAL abaixo); separadamente de,
• uma camada de classes com operações com significado para o negócio, e que não dependem directamente da base de dados e podem ser obtidas por composição das operações CRUD primitivas (ex.: class BookBLL abaixo).
2.1 classe BookDAL:
public class BookDAL {
private int idBook;
private String title;
private String editor;
private java.sql.Date date;
private String ISBN;
private String edition;
//
private List<Author> authors = new ArrayList<Author>();
private DBAccessObj dbo;
public BookDAL() {
this.dbo = new DBAccessObj();
this.dbo.openConnection();
}
public BookDAL(DBAccessObj dbo) {
this.dbo = dbo;
this.dbo.openConnection();
}
public int getID() { return this.idBook; }
public void setTitle(String title) { this.title = title; }
public String getTitle() { return title; }
public void setEditor(String editor) { this.editor = editor; }
public String getEditor() { return editor; }
public void setDate(java.sql.Date date) { this.date = date; }
public java.sql.Date getDate() { return date; }
public void setISBN(String ISBN) { this.ISBN = ISBN; }
public String getISBN() { return ISBN; }
public void setEdition(String edition) { this.edition = edition; }
public String getEdition() { return edition; }
public List<Author> getAuthors() { return this.authors; }
public void create() throws SQLException{
String sqlCommand =
"INSERT INTO Book (ISBN, Title, Edition, Editor) VALUES('" +
this.ISBN + "', '" + this.title + "', '" + this.edition + "', '" + this.editor + "')";
this.dbo.executeSQL(sqlCommand);
}
public void retrieve(int id) throws SQLException{
String sqlCommand =
"SELECT ISBN, Title, DateEdition, Edition, Editor FROM Book WHERE ID = '" + id + "'";
ResultSet book;
book = this.dbo.executeQuery(sqlCommand);
if (book.next()){
this.idBook = id;
this.ISBN = book.getString("ISBN");
this.title = book.getString("Title");
this.date = book.getDate("DateEdition");
this.edition = book.getString("Edition");
this.editor = book.getString("Editor");
}
}
public void retrieveByISBN(String isbn) throws SQLException{
String sqlCommand =
"SELECT ID, Title, DateEdition, Edition, Editor FROM Book WHERE ISBN = '" + isbn + "'";
ResultSet book;
book = this.dbo.executeQuery(sqlCommand);
if (book.next()){
this.idBook = book.getInt("ID");
this.title = book.getString("Title");
this.date = book.getDate("DateEdition");
this.edition = book.getString("Edition");
this.editor = book.getString("Editor");
this.ISBN = isbn;
}
}
public void update() {
String sqlCommand =
"UPDATE Book SET ISBN = '" + this.ISBN + "', Title = '" + this.title + "', Edition = '" +
this.edition + "', Editor = '" + this.editor + "' WHERE ID = '" + this.idBook + "'";
this.dbo.executeSQL(sqlCommand);
}
public void delete() {
String sqlCommand = "DELETE FROM Book WHERE ID = '" + this.idBook + "'";
this.dbo.executeSQL(sqlCommand);
}
public ResultSet retrieveThisBookAuthors(DBAccessObj dbo) throws SQLException{
String sqlCommand =
"SELECT B.ID, B.ISBN, B.Title, A.ID, A.Name, A.Surname FROM BookAuthor BA, Author A, Book B WHERE BA.BookID = B.ID AND BA.AuthorID = A.ID AND B.ID = " + this.getID() + " ORDER BY 3, 2";
ResultSet books;
dbo.openConnection();
books = dbo.executeQuery(sqlCommand);
return books;
}
public void fillThisBookAuthors() throws SQLException{
String sqlCommand = "SELECT A.ID, A.Name, A.Surname FROM BookAuthor BA, Author A, Book B WHERE BA.BookID = B.ID AND BA.AuthorID = A.ID AND B.ID = " + this.getID() + " ORDER BY 3, 2";
ResultSet booksA;
this.dbo.openConnection();
booksA = this.dbo.executeQuery(sqlCommand);
while (booksA.next()){
Author au = new Author();
au.setName(booksA.getString("Name"));
au.setSurname(booksA.getString("Surname"));
this.authors.add(au);
}
}
public static ResultSet retrieveAllBooks(DBAccessObj dbo) throws SQLException{
String sqlCommand = "SELECT ISBN, Title, DateEdition, Edition, Editor FROM Book";
ResultSet books;
dbo.openConnection();
books = dbo.executeQuery(sqlCommand);
return books;
}
public static ResultSet retrieveAllBooksAuthors(DBAccessObj dbo) throws SQLException{
String sqlCommand = "SELECT B.ID, B.ISBN, B.Title, A.ID, A.Name, A.Surname FROM BookAuthor BA, Author A, Book B WHERE BA.BookID = B.ID AND BA.AuthorID = A.ID ORDER BY 1, 6, 5";
ResultSet books;
dbo.openConnection();
books = dbo.executeQuery(sqlCommand);
return books;
}
2.2 classe ManageBooksBLL:
public class ManageBooksBLL {
public ManageBooksBLL () { }
public int requisitarBook (Book book, Borrower leitor) throws ManageBookException {
…
}
public int requisitarBook (int bookID, int leitorID) throws ManageBookException {
…
}
public int devolverBook (Book book) throws ManageBookException{
…
}
public int devolverBook (int bookID) throws ManageBookException {
…
}
}
Nesta abordagem, o encapsulamento de dados e operações aparece, orientado às entidades do domínio do problema (classes Entidade ou persistentes), na camada DAL.
A camada BLL (Business Logic Layer) contém operações orientadas aos casos de uso a implementar na aplicação, podendo portanto ser vista como uma camada de fornecimento de serviços para a camada acima, de Interface com o utilizador (UI, User Interface).
Em termos práticos, dependendo da quantidade de operações complexas num programa (diferentes de CRUD), podemos ainda misturar a DAL e BLL da 2ª abordagem, passando isso por acrescentar nas classes DAL os poucos métodos BLL que tivéssemos, eliminando as classes BLL.
De notar, em ambas as abordagens, a utilização da classe DBAccessObj, cujo desenvolvimento foi tratado no artigo anterior, para acesso à base de dados.
O zip com o resultado final pode, como de costume, ser solicitado nos comentários a este artigo.
Outros artigos relacionados:
- Exemplo de Aplicação Java Swing com BD Oracle - 1
- Exemplo de Aplicação Java Swing com BD Oracle - 2
- Exemplo de Aplicacao Java Swing com BD Oracle - 4
Olá! O zip com o projeto da camada de lógica de negócio desenvolvida neste artigo está em https://docs.google.com/open?id=0B0zl-Rzbx3qgQnQ1ZDRKeU5Valk
ResponderEliminarAo descompactar, os ficheiros Java devem ficar numa pasta ...\libraryProjectBLL\src\libraryBLL
Importar no Netbeans, criando um projeto "with existing sources".
Nas libraries do projeto acrescentar a referencia ao projeto HelperDB.
Bom trabalho!