Então chegou o dia no qual você conheceu Grails, se apaixonou pelo bichinho mas não sabe ainda como configurá-lo para acessar sua base de dados legada. Ao primeiro contato com Grails, uma impressão que surge é que, para criarmos algo com o bichinho, precisamos partir do zero no que diz respeito a base de dados. Felizmente nada poderia ser mais distante da verdade.
Se você já possui uma base de dados legada, e gostaria de reaproveitá-la em sua aplicação feita em Grails, apresento-lhe a propriedade mapping, responsável por permitir ao desenvolvedor customizar o modo como Grails acessa suas bases de dados (leia aqui: o chato do legado). É neste bloco de código aonde definimos, por exemplo, o nome dos campos que queremos acessar em nossa aplicação.
Sendo assim, suponhamos que eu já possua em um banco de dados (não irei explicar aqui como configurar a conexão com o mesmo, pois o assunto do tópico consiste apenas em como customizar o mapeamento de nossas classes com suas respectivas tabelas) uma tabela chamada tbUsuario. Esta foi definida tal como descrito abaixo (não costumo dar estes nomes a meus campos. Irei usar aqui nomes que se afastem o máximo possível dos padrões normalmente criados pelo Grails):
create table tbUsuario ( idUsuario varchar(36) not null, strNome varchar(128) not null, strLogin varchar(64) not null, strSenha varchar(128) not null, primary key (Id) )
Nossa tabela utiliza como chave primária o campo idUsuario que armazena valores gerados usando o algoritmo UUID, diferente do padrão definido pelo Grails quando trabalhamos com MySQL por exemplo (neste caso, Grails utiliza valores auto incrementais).
Suponhamos agora, que nossa classe de domínio possua o código definido abaixo:
class Usuario { String nome String login String senha static constraints = { nome(maxSize: 128, nullable:false, blank:false, unique: true) login(maxSize: 64, nullable:false, blank:false, unique: true) senha(maxSize: 128, nullable:false, blank:false) } }
Se fossemos usar o padrão do Grails para a geração de tabelas no MySQL, gerariamos em nosso banco uma tabela tal como a descrita no código abaixo:
create table usuario { id integer not null auto_increment, version integer not null, // para versionamento do banco, o Grails cria este campo por default nome varchar(128) not null, login varchar(128) not null, senha varchar(128) not null, primary key (id), // e algum código para a geração dos indices unicos para os campos login e nome }
Como pode ser observado, a tabela gerada por default é muito diferente da que intencionamos usar. Para resolver este problema, iremos incluir o bloco de código mapping em nossa classe de domínio, tal como no código abaixo:
class Usuario { String id // repare: estou redefinindo o atributo id como String. String nome String login String senha static constraints = { nome(maxSize: 128, nullable:false, blank:false, unique: true) login(maxSize: 64, nullable:false, blank:false, unique: true) senha(maxSize: 128, nullable:false, blank:false) } static mapping = { table 'tbUsuario' version false id column:'idUsuario', generator:'uuid' nome column:'strNome' login column:'strLogin' senha column:'strSenha' } }
Vamos agora analisar o que foi feito no bloco mapping linha a linha (ou quase):
table 'tbUsuario'
Simples: defino qual o nome da tabela na qual os dados se encontram armazenados.
version false
O Grails por default cria um campo chamado version em suas tabelas para versionamento dos dados. Podemos desabilitar este padrão usando o comando acima. Dado que em nossa base de dados legada não existe campo similar, ignorar este detalhe iria travar nossa aplicação.
id column:'idUsuario', generator:'uuid'
Como não iremos usar o padrão para armazenamento de chaves primárias, que varia de acordo com o banco de dados (MySQL, por exemplo, tem por default campos incrementais no que diz respeito a chaves primárias), precisamos redefinir nossa coluna id.
No caso, primeiro definimos qual o nome da coluna na qual os dados estão armazenados. Em seguida, definimos qual o algoritmo usado na geração destes valores. Em nosso caso, o algoritmo UUID (já inclusive escrevi sobre isto aqui).
Com relação aos demais campos, apenas foi definido o nome relacionado à tabela em questão:
nome column:'strNome' login column:'strLogin' senha column:'strSenha'
E por incrível que pareça, basicamente é isto o que você precisa fazer caso queira lidar com bases de dados legadas. Todo o código CRUD referente a classe de domínio em questão será feito com base nestas customizações.
Caso queira se aprofundar mais sobre o assunto, sugiro que dê uma lida na própria documentação do Grails (aliás, excelente) clicando aqui.
Muito bom e providencial seu post Kico. Estou avaliando a utilização do grails numa base de um sistema legado.. O banco (sybase) tem uma parte das regras de negócio em store procedures.. Neste caso qual seria a “melhor maneira” mais elegante de executar estas procedures e se beneficiar das vantagens de validações e etc centrado na classe de dominio? Criar uma classe de dominio com as chamadas (como fazer sem que a mesma crie entidades no banco)? Bem parabens pelo excelente conteudo do blog!!! abraço!
Maneiro esse post. Isso me lembrou o ‘magic models’ do Dr. Nic. Seria uma indeia interessante pra um plugin de grails.
*O magic models gera um modelo a partir de um banco de dados pre-existente com relacionamentos, validaçao, etc…
opa.. consegui encontrar a solução com a utilização de “command objects” (http://grails.org/doc/1.0.x/guide/single.html#6.1.9%20Command%20Objects). Valeu!
Esse static mapping é uma manga… salva até uma aplicação nova em uma base Oracle… o chato é que o tal do oracle tem um limite de 30 caracteres para identificador… Tem como resolver pelo mapping a nomenclatura de uma tabela ou campo que é criada por um hasMany por exemplo? ocasionalmente vira uma coisa do tipo: esse_dominio_possui_uma_lista_de_outros_dominios_id….