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