CRUD
O caso de uso mais comum em aplicações empresariais é o CRUD.
O NEO disponibiliza um controller e algumas tags justamente para relizar
esse tipo de operação.
Para fazer um CRUD precisamos dos seguintes componentes:
- Entidade: POJO mapeado no hibernate que representa a tabela no banco de dados
- DAO: Fornece os métodos de acesso aos dados
- Service: Possui alguma regra de negócio
- Controller: Processará a requisição do usuário
- JSP listagem: JSP que define a tela de listagem de dados
- JSP entrada: JSP que define a tela de entrada de dados
A entidade, o dao e o service já foram explicados em capítulos anteriores. O Controller é um CrudController
que extende o MultiActionController e já possui alguns métodos implementados.
Os JSPs de listagem e entrada são JSPs comuns.
Vejamos um CRUD de Uf. O Uf possuirá os campos id, nome e sigla.
package org.neoframework.exemplo.bean;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import br.com.linkcom.neo.validation.annotation.MaxLength;
import br.com.linkcom.neo.validation.annotation.Required;
@Entity
@SequenceGenerator(name = "sq_uf", sequenceName = "sq_uf")
public class Uf {
Integer id;
String nome;
String sigla;
@Id
@GeneratedValue(strategy=GenerationType.AUTO, generator="sq_uf")
public Integer getId() {
return id;
}
public String getNome() {
return nome;
}
public String getSigla() {
return sigla;
}
public void setId(Integer id) {
this.id = id;
}
public void setNome(String nome) {
this.nome = nome;
}
public void setSigla(String sigla) {
this.sigla = sigla;
}
}
POJO que representa a tabela. Registrado no Hibernate.
package org.neoframework.exemplo.dao;
import org.neoframework.exemplo.bean.Uf;
import br.com.linkcom.neo.persistence.GenericDAO;
public class UfDAO extends GenericDAO<Uf> {
}
DAO para Uf
package org.neoframework.exemplo.service;
import org.neoframework.exemplo.bean.Uf;
import br.com.linkcom.neo.service.GenericService;
public class UfService extends GenericService<Uf> {
}
Service para Uf
Como foi visto anteriormente a classe Uf será registrada no Hibernate por possuir a anotação @Entity.
As classes DAO e Service serão registradas no Spring porque extendem GenericDAO e GenericService
(não sendo necessário utilizar a anotação @Bean).
Já existem métodos no DAO e Service para o controle de Crud. Esses métodos já vem implementados,
mas podem ser sobrescritos caso deseje modificar alguma funcionalidade.
O Controller deve ser um CrudController e também deve ser configurado com as entidades em questão.
package org.neoframework.exemplo.controller;
import org.neoframework.exemplo.bean.Uf;
import br.com.linkcom.neo.controller.Controller;
import br.com.linkcom.neo.controller.crud.CrudController;
import br.com.linkcom.neo.controller.crud.FiltroListagem;
@Controller(path="/modulo/crud/Uf")
public class UfCrud extends CrudController<FiltroListagem, Uf, Uf> {
}
Controller para o CRUD de Uf
O CrudController recebe três argumentos genéricos. O primeiro é a classe que será utilizada na listagem,
essa classe deve extender FiltroListagem. Como não temos nenhum filtro, utilizamos o próprio FiltroListagem.
O segundo argumento é a classe que será utilizada na tela de entrada de dados, geralmente é a mesma classe
do bean.
E o terceiro argumento é a classe do bean (entidade do hibernate) que está sendo manipulado.
Crie um arquivo JSP no caminho "/WebRoot/WEB-INF/jsp/modulo/crud/ufListagem.jsp" e adicione o seguinte conteúdo:
[JSP]
<%@ taglib prefix="n" uri="neo"%>
<%@ taglib prefix="t" uri="template"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<t:listagem>
<t:janelaResultados>
<t:tabelaResultados>
<t:property name="id"/>
<t:property name="nome"/>
<t:property name="sigla"/>
</t:tabelaResultados>
</t:janelaResultados>
</t:listagem>
JSP de listagem
Agora crie um novo arquivo JSP no caminho "/WebRoot/WEB-INF/jsp/modulo/crud/ufEntrada.jsp" e adicione o seguinte conteúdo:
[JSP]
<%@ taglib prefix="n" uri="neo"%>
<%@ taglib prefix="t" uri="template"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<t:entrada>
<t:janelaEntrada>
<t:tabelaEntrada>
<t:property name="id"/>
<t:property name="nome"/>
<t:property name="sigla"/>
</t:tabelaEntrada>
</t:janelaEntrada>
</t:entrada>
JSP de entrada
O NEO possui tags exclusivas para as telas de listagem e entrada de dados.
É possível alterar o layout ou até mesmo algum funcionamento dessas tags alterando seus templates.
O CrudController coloca no escopo informações para essas tags utilizarem. Por isso não é necessário
informar onde estam as listas ou se o modo é input ou output.
Para executar este exemplo é necessário criar as seguintes tabelas (estes scripts foram gerados para o
Postgres, caso esteja testando em outro banco de dados talvez seja necessário alterar o script):
CREATE SEQUENCE sq_uf;
CREATE TABLE uf
(
id integer NOT NULL,
nome character varying(100) NOT NULL,
sigla character varying(2) NOT NULL,
CONSTRAINT uf_pkey PRIMARY KEY (id)
);
Alterando o comportamento padrão
O CrudController e o GenericDAO possibilitam a alteração do comportamento padrão para isso alguns métodos
são disponibilizados. A tabela abaixo mostra os principais métodos e a funcionalidade implementada por eles.
Veja a API dessas classes para maiores informações.
Classe | Método | Funcionalidade |
CrudController | listagem | Método que deve ser sobrescrito para adicionar novas funcionalidades para a listagem. Esse método é chamado antes de ir para a tela de listagem de dados |
CrudController | getListagemModelAndView | Retorna o ModelAndView que representa o JSP de listagem |
CrudController | entrada | Método que deve ser sobrescrito para adicionar novas funcionalidades para a entrada. Esse método é chamado antes de ir para a tela de entrada de dados |
CrudController | getEntradaModelAndView | Retorna o ModelAndView que representa o JSP de entrada |
CrudController | carregar | Carrega o banco de dados um determinado bean. Esse método recebe um bean apenas com o id configurado, e deve retornar um bean completo. |
CrudController | criar | Cria um novo bean |
CrudController | salvar | Salva determinado bean no banco de dados |
CrudController | excluir | Exclui determinado bean |
GenericDAO | updateListagemQuery | Atualiza a query de listagem, recebe um objeto da mesma classe do filtro do CRUD |
GenericDAO | updateEntradaQuery | Atualiza a query de entrada de dados |
GenericDAO | updateSaveOrUpdate | Atualiza o SaveOrUpdateStrategy para salvar o bean |
Adicionando um filtro à listagem
Para utilizar um filtro na listagem, os seguintes passos são necessários:
Criar uma classe de filtro como no exemplo:
package org.neoframework.exemplo.controller;
import br.com.linkcom.neo.controller.crud.FiltroListagem;
public class UfFiltro extends FiltroListagem {
String nome;
public String getNome() {
return nome;
}
public void setNome(String nome) {
this.nome = nome;
}
}
Informar ao controller a classe de filtro que estamos utilizando:
package org.neoframework.exemplo.controller;
import org.neoframework.exemplo.bean.Uf;
import br.com.linkcom.neo.controller.Controller;
import br.com.linkcom.neo.controller.crud.CrudController;
import br.com.linkcom.neo.controller.crud.FiltroListagem;
@Controller(path="/modulo/crud/Uf")
public class UfCrud extends CrudController<UfFiltro, Uf, Uf> {
}
Alterar o JSP para adicionar o campo na tela.
[JSP]
<%@ taglib prefix="n" uri="neo"%>
<%@ taglib prefix="t" uri="template"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<t:listagem>
<t:janelaFiltro>
<t:tabelaFiltro>
<t:property name="nome"/>
</t:tabelaFiltro>
</t:janelaFiltro>
<t:janelaResultados>
<t:tabelaResultados>
<t:property name="id"/>
<t:property name="nome"/>
<t:property name="sigla"/>
</t:tabelaResultados>
</t:janelaResultados>
</t:listagem>
Alterar o comportamento da query para utilizar o filtro:
package org.neoframework.exemplo.dao;
import org.neoframework.exemplo.bean.Uf;
import org.neoframework.exemplo.controller.UfFiltro;
import br.com.linkcom.neo.controller.crud.FiltroListagem;
import br.com.linkcom.neo.persistence.GenericDAO;
import br.com.linkcom.neo.persistence.QueryBuilder;
public class UfDAO extends GenericDAO<Uf> {
@Override
public void updateListagemQuery(QueryBuilder<Uf> query, FiltroListagem _filtro) {
UfFiltro filtro = (UfFiltro) _filtro;
query.whereLike("uf.nome", filtro.getNome());
}
}
A query recebida como parâmetro já possui a cláusula FROM configurada.
Por isso foi apenas necessário criar a clásula where.