Fechando uma série com 3 posts que descrevem algumas características do Spring Roo para a camada de persistência, neste último post vou demonstrar como criar entidades persistentes a partir de uma base de dados relacional, utilizando engenharia reversa via o add-on DBRE (Database Reverse Engineering) do Spring Roo.
O diferencial do Roo, em relação a outras ferramentas de engenharia reversa, é a possibilidade de re-utilizar essa funcionalidade durante todo o ciclo de desenvolvimento, não se limitando apenas na fase inicial de codificação.
Modelo de dados
Vou usar o mesmo projeto demonstração dos outros dois posts, um CRUD de produtos, no MySQL com as seguintes tabelas:
Projeto Roo
Para experimentar a engenharia reversa do Spring Roo é interessante começar um projeto novo. A seguir, as instruções necessárias para montar o projeto:
Metadata no Banco de dados
O DBRE do Roo precisa de uma conexão com o banco de dados para consultar a estrutura das tabelas (metadados). Isso é feito através da interface DatabaseMetadata implementada pelo driver JDBC subjacente. Essas informações são mantidas pelo Roo em formato XML, e a partir deles o Roo gera o código das entidades persistentes.
Para utilizar o DBRE pela primeira vez, são necessários alguns comandos para configurar o add-on. Para quem já testou o DBRE esses passos podem ser ignorados. Primeiro é necessário instalar o driver JDBC do MySQL, por isso consultamos o seu id na lista de add-ons:
Pronto, agora para consultar a estrutura das tabelas no banco de dados e listar as informações no Shell basta executar a seguinte instrução:
Geração de Entidades
A geração do código das entidades ocorre através do comando database reverse engineer. A opção package é opcional e indica em qual pacote as classes devem ser geradas. Veja:
Depois de executar esse comando o Roo cria o arquivo .roo-dbre com a estrutura do banco e, as classes Categoria e Produto. Para cada classe o Roo também cria três aspectos, que foram apresentados no primeiro post: _Roo_Configurable, _Roo_Entity e _Roo_ToString.
Porém, com o DBRE o Roo marca a entidade com a anotação @RooDbManaged e cria um quarto tipo de aspecto: _Roo_DbManaged. Nesse aspecto o Roo coloca o código de mapeamento JPA gerado pela engenharia reversa. Veja o exemplo do aspecto Produto_Roo_DbManaged:
As classes Produto e Categoria ficam praticamente sem código, só com as anotações do Roo. A intenção do Roo é inferir o mínimo possível no código Java sem tirar a autonomia do programador, que pode a qualquer momento sobrescrever na própria entidade um atributo ou remover a marcação @RooDbManaged.
Outras opções também podem ser utilizadas com o comando database reverse engineer:
Com mais dois comandos e aplicação já pode ser testada:
Relacionamentos
O DBRE compreende o relacionamento entre entidades através das chaves estrangeiras (foreign key) existentes no banco de dados. No exemplo utilizado aqui, o Roo resolve com associção many-valued bidirecional sendo o Produto relacionado (ManyToOne) a uma Categoria. Já a Categoria com um conjunto de Produtos (OneToMany).
A geração do código seria diferente se, por exemplo, o campo categoria da tabela produto fosse a chave primária. Dessa forma o Roo montaria o relacionamento OneToOne da Categoria com o Produto, nesse caso unidirecional na classe Categoria.
O Roo também suporta a definição de chave primária com duas ou mais colunas, maiores detalhes estam disponíveis na documentação.
Padrão de nomes
O Roo define um algoritmo simples para definir o nome das classes e atributos a partir das tabelas e colunas. Para a tabela os caracteres "_", "-" ou "\" são separadores de nome, veja exemplos:
O comportamento é parecido para as colunas:
Outras referências:
Eder Magalhães
www.yaw.com.br
twitter.com/youandwe
twitter.com/edermag
O diferencial do Roo, em relação a outras ferramentas de engenharia reversa, é a possibilidade de re-utilizar essa funcionalidade durante todo o ciclo de desenvolvimento, não se limitando apenas na fase inicial de codificação.
Modelo de dados
Vou usar o mesmo projeto demonstração dos outros dois posts, um CRUD de produtos, no MySQL com as seguintes tabelas:
Projeto Roo
Para experimentar a engenharia reversa do Spring Roo é interessante começar um projeto novo. A seguir, as instruções necessárias para montar o projeto:
roo> project --topLevelPackage br.com.yaw.produtos roo> persistence setup --provider HIBERNATE --database MYSQL --databaseName roodb --hostName localhost --userName roo --password rooImportante: os parâmetros databaseName, hostName, userName e password mudam conforme a instalação realizada no banco.
Metadata no Banco de dados
O DBRE do Roo precisa de uma conexão com o banco de dados para consultar a estrutura das tabelas (metadados). Isso é feito através da interface DatabaseMetadata implementada pelo driver JDBC subjacente. Essas informações são mantidas pelo Roo em formato XML, e a partir deles o Roo gera o código das entidades persistentes.
Para utilizar o DBRE pela primeira vez, são necessários alguns comandos para configurar o add-on. Para quem já testou o DBRE esses passos podem ser ignorados. Primeiro é necessário instalar o driver JDBC do MySQL, por isso consultamos o seu id na lista de add-ons:
roo> addon list roo> addon install id --searchResultId 39Sobre o último comando, esse efetivamente instala o driver e 39 é id do #jdbcdriver do MySQL.
Pronto, agora para consultar a estrutura das tabelas no banco de dados e listar as informações no Shell basta executar a seguinte instrução:
roo> database introspect --schema roodb
<database name="no-schema-required">
<table name="categoria">
<column name="id" primaryKey="true" required="true" size="10"
type="4,INT"/>
<column name="nome" primaryKey="false" required="true" size="50"
type="12,VARCHAR"/>
<foreign-key foreignTable="produto" name="fk_categoria" onDelete="none"
onUpdate="none">
<option key="exported" value="true"/>
<reference foreign="categoria" local="id"/>
</foreign-key>
<unique name="PRIMARY">
<unique-column name="id"/>
</unique>
</table>
<table name="produto">
<column name="id" primaryKey="true" required="true" size="10"
type="4,INT"/>
<column name="descricao" primaryKey="false" required="true" size="60"
type="12,VARCHAR"/>
<column name="preco" primaryKey="false" required="true" size="22"
type="8,DOUBLE"/>
<column name="categoria" primaryKey="false" required="true" size="10"
type="4,INT"/>
<foreign-key foreignTable="categoria" name="fk_categoria" onDelete="none"
onUpdate="none">
<option key="exported" value="false"/>
<reference foreign="id" local="categoria"/>
</foreign-key>
<unique name="PRIMARY">
<unique-column name="id"/>
</unique>
<index name="fk_categoria">
<index-column name="categoria"/>
</index>
</table>
</database>
Outras opções para executar esse comando:- schema no-schema-required: uma opção ao invés do nome do schema.
- enableViews: habilita a engenharia reversa para visões do banco de dados (View).
- file: guarda a pesquisa de metadados em arquivo XML.
Geração de Entidades
A geração do código das entidades ocorre através do comando database reverse engineer. A opção package é opcional e indica em qual pacote as classes devem ser geradas. Veja:
roo> database reverse engineer --schema roodb --package ~.model Created SRC_MAIN_JAVA/br/com/yaw/produtos/model Created SRC_MAIN_JAVA/br/com/yaw/produtos/model/Categoria.java Created SRC_MAIN_JAVA/br/com/yaw/produtos/model/Produto.java Updated SRC_MAIN_RESOURCES/META-INF/persistence.xml Created SRC_MAIN_JAVA/br/com/yaw/produtos/model/Produto_Roo_ToString.aj Created SRC_MAIN_JAVA/br/com/yaw/produtos/model/Produto_Roo_DbManaged.aj Created SRC_MAIN_JAVA/br/com/yaw/produtos/model/Categoria_Roo_DbManaged.aj Created SRC_MAIN_JAVA/br/com/yaw/produtos/model/Produto_Roo_Configurable.aj Created SRC_MAIN_JAVA/br/com/yaw/produtos/model/Categoria_Roo_Entity.aj Created SRC_MAIN_JAVA/br/com/yaw/produtos/model/Produto_Roo_Entity.aj Created SRC_MAIN_JAVA/br/com/yaw/produtos/model/Categoria_Roo_ToString.aj Created SRC_MAIN_JAVA/br/com/yaw/produtos/model/Categoria_Roo_Configurable.aj Created ROOT/.roo-dbre
Depois de executar esse comando o Roo cria o arquivo .roo-dbre com a estrutura do banco e, as classes Categoria e Produto. Para cada classe o Roo também cria três aspectos, que foram apresentados no primeiro post: _Roo_Configurable, _Roo_Entity e _Roo_ToString.
Porém, com o DBRE o Roo marca a entidade com a anotação @RooDbManaged e cria um quarto tipo de aspecto: _Roo_DbManaged. Nesse aspecto o Roo coloca o código de mapeamento JPA gerado pela engenharia reversa. Veja o exemplo do aspecto Produto_Roo_DbManaged:
//...
privileged aspect Produto_Roo_DbManaged {
@ManyToOne
@JoinColumn(name = "categoria", referencedColumnName = "id", nullable = false)
private Categoria Produto.categoria;
@Column(name = "descricao", columnDefinition = "VARCHAR", length = 60)
@NotNull
private String Produto.descricao;
@Column(name = "preco", columnDefinition = "DOUBLE")
@NotNull
private Double Produto.preco;
public Categoria Produto.getCategoria() {
return this.categoria;
}
public void Produto.setCategoria(Categoria categoria) {
this.categoria = categoria;
}
public String Produto.getDescricao() {
return this.descricao;
}
public void Produto.setDescricao(String descricao) {
this.descricao = descricao;
}
public Double Produto.getPreco() {
return this.preco;
}
public void Produto.setPreco(Double preco) {
this.preco = preco;
}
}
As classes Produto e Categoria ficam praticamente sem código, só com as anotações do Roo. A intenção do Roo é inferir o mínimo possível no código Java sem tirar a autonomia do programador, que pode a qualquer momento sobrescrever na própria entidade um atributo ou remover a marcação @RooDbManaged.
Outras opções também podem ser utilizadas com o comando database reverse engineer:
- testAutomatically: cria o código de teste de integração para as entidades.
- enableViews: habilita a engenharia reversa para Visões (View).
- includeTables: filtra as tabelas que serão processadas, por exemplo as tabelas com o prefixo prod: --includeTables "prod*"
- excludeTables: opção para restringir tabelas, por exemplo tabelas com prefixo sys: --excludeTables "sys*"
Com mais dois comandos e aplicação já pode ser testada:
roo> controller all --package ~.web roo> perform packageCaso a tabela sofra alguma modificação, uma nova coluna por exemplo, é possível em qualquer momento executar novamente o comando database reverse engineer que o resto do trabalho é feito pelo Roo.
Relacionamentos
O DBRE compreende o relacionamento entre entidades através das chaves estrangeiras (foreign key) existentes no banco de dados. No exemplo utilizado aqui, o Roo resolve com associção many-valued bidirecional sendo o Produto relacionado (ManyToOne) a uma Categoria. Já a Categoria com um conjunto de Produtos (OneToMany).
A geração do código seria diferente se, por exemplo, o campo categoria da tabela produto fosse a chave primária. Dessa forma o Roo montaria o relacionamento OneToOne da Categoria com o Produto, nesse caso unidirecional na classe Categoria.
O Roo também suporta a definição de chave primária com duas ou mais colunas, maiores detalhes estam disponíveis na documentação.
Padrão de nomes
O Roo define um algoritmo simples para definir o nome das classes e atributos a partir das tabelas e colunas. Para a tabela os caracteres "_", "-" ou "\" são separadores de nome, veja exemplos:
- Tabela produto > Classe Produto
- Tabela produto_categoria > ProdutoCategoria
- Tabela PRODUTO-ITEM > ProdutoItem
O comportamento é parecido para as colunas:
- Coluna preco > Atributo preco
- Coluna codigo_produto > Atributo codigoProduto
Outras referências:
- Bastidores do Spring Roo: A camada de persistência (post 1)
- Criação de consultas com o Spring Roo (post 2)
- Posts do Spring Roo no Globalcoders;
- Documentação de referência do Spring Roo;
- Twitter do Roo;
Eder Magalhães
www.yaw.com.br
twitter.com/youandwe
twitter.com/edermag

Comentários
Abraço