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
    public class Uf {

    	Integer id;
    	String nome;
    	String sigla;

    	@Id
    	@GeneratedValue(strategy=GenerationType.AUTO)
    	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.
Os JSPs:

    [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

    [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.
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.