Geração de SQL automático

4 views
Skip to first unread message

Marcos George

unread,
Apr 2, 2009, 2:52:36 PM4/2/09
to Infra - Integrated Frameworks
Pessoal, gostaria de discutir com vcs a geração de SQL automático. Eu
tive umas idéias e quero saber a opinião de vcs sobre o assunto.

Uma das premissas do Infra é a flexibilidade. Por isso, eu idealizei
algo que traga a geração automática de SQL sem perder a flexibilidade.
Hoje, o Infra só permite a carga/alteração de objetos feita por meio
de templates. Mas, o meu desejo (e acredito que seja o de todos) é que
os templates sejam a exceção e não a regra.

A seguir, vcs poderão observar trechos de código, e antes que alguém
pergunte vou explicar logo: Eu também estou propondo uma mudança no
SQLCommand. Hoje, ele só retém o nome do template e os parâmetros. A
minha proposta é que ele possua uma propriedade SQL (como qualquer
componente de acesso a dados do delphi). Por que isso? Para que
possamos alterar o SQL como bem quisermos mesmo depois da geração
automática.

Vamos ao código:

//1º Caso)
//Geração de query automatica

vConfig := PersistenceService.GetConfiguration;
// Customizações aki

vSessionFactory := vConfig.BuildSessionFactory;
vSession := vSessionFactory.OpenSession;

// O session constrói um SQL automaticamente e
// lê o mapeamento de um arquivo em disco (pode ser um xml, por sua
flexibilidade)

// um possível layout de TAccount.xml é:
//<infra-mapping>
// <class name="accounts.Account" table="ACCOUNTS" alias="acc">
// <id name="id" column="ID">
// <generator name="ACCOUNTS_IDGEN"/>
// </id>
// <property name="Name" column="ACCOUNTNAME"/>
// <property name="AccountNumber" column="ACCOUNTNUMBER"/>
// <property name="InitialBalance" column="INITIALBALANCE"/>
// <property name="CurrentBalance" column="CURRENTBALANCE"/>
// </class>
//</infra-mapping>

// Acho que seria melhor ler o mapeamento de um arquivo pq o objeto
não precisa
// estar criado para se obter informações sobre ele, o que seria o
caso de se usar as anotações
vSQLCommand := vSession.CreateQuery('TAccount');

// o vSQLCommand deveria ter na sua propriedade SQL o seguinte
comando:
// select acc.id, acc.accountnumber, acc.accountname,
acc.initialbalance, acc.currentbalance
// from accounts acc
// where acc.id = :oid

// Agora, podemos especificar o objeto desejado
vSQLCommand.Params['oid'] := 10;

// Finalmente, o objeto é criado e suas propriedades setadas de
acordo com o
// mapeamento
vAccount := vSQLCommand.GetResult as IAccount;

//2º Caso)
// Leitura da query de um template

vConfig := PersistenceService.GetConfiguration;
// Customizações aki

vSessionFactory := vConfig.BuildSessionFactory;
vSession := vSessionFactory.OpenSession;

// Neste caso o session lê um arquivo da pasta de templates
vSQLCommand := vSession.CreateQueryFromTemplate
('SelectAccountByID');

// o CreateQueryFromTemplate já deveria carregar o conteúdo do
arquivo para
// para o vSQLCommand.SQL

// Agora, podemos especificar o objeto desejado
vSQLCommand.Params['oid'] := 10;

// Finalmente, o objeto é criado e suas propriedades setadas de
acordo com o
// mapeamento
vAccount := vSQLCommand.GetResult as IAccount;

Marcos Barreto

unread,
Apr 2, 2009, 8:05:34 PM4/2/09
to infra...@googlegroups.com
Bem Marcos George, vou descrever aqui a minha opinião e se me permite, vou corrigir alguns equivocos no seu texto.

Hoje temos uma hierarquia de classes responsável pela devolução de uma instrução SQL. A classe base chama-se hoje TTemplateReader e dela derivamos o TTemplateReader_IO. TTemplateReader_IO vai em um arquivo texto no hd e pega a instrução sql. Isso é extremamente flexível pois podemos fazer herança de TTemplateReader ou um de seus filhos para poder ler as instruções de onde quisermos. ex:
  • TTemplateReaderXML - retorna a instrução SQL solicitada lida de um arquivo XML;
  • TTemplateReaderDB - retorna a instrução SQL solicitada lida do proprio banco de dados da aplicação;
  • TTemplateReaderAuto - gera a instrução SQL baseado em algum mapeamento via anotação nas classes; e por ai vai
Como discuti com o MG antes dele postar esta mensagem eu acho que já temos quase tudo que precisamos para poder fazer o TTemplateReaderAuto.

E acho que nao vai mudar em quase nada na estrutura de carregamento e persistencia existente.

Hj para carregarmos um objeto nós PODEMOS fazer isso, eu disse podemos por que existe outras formas:

var
  vObj: IAccount;
  vSQLCommand: ISQLCommandQuery;
  vSession: ISession;
begin
  // cria um objeto conta e define sua propriedade id
  vObj := TAccount.Create;
  vObj.Id.AsInteger := 1;

  // obtem o session da fábrica
  vSession := FSessionFactory.OpenSession;

  // Cria um command query com as informações sobre o objeto e o templante a ser usado durante a carga
  // cLoadAccountByIDTemplateName é simplesmente o nome do arquivo (sem extensão) que contem a SQL
  vSQLCommand := pSession.CreateNamedQuery(cLoadAccountByIDTemplateName, vObj);

  // vSQLCommand possui GetList e GetResult, no casso aqui como estamos carregando a conta pelo OID só virá um registro
  vObj := vSQLCommand.GetResult as IAccount;

  // Neste ponto o vObj tem agora todos seus atributos preenchido com o dado do banco,
  // sem necessidade alguma de mapeamento ou anotação
end;

Muitos de vocês podem estar se perguntando que escrever um arquivo com cada instrução SQL é oneroso, realmente é, mas como disse acima estas SQL podem ser definidas de outras formas (um unico XML por exemplo com todas as SQL). E para aqueles que talvez torceram a boca quando leu a coisa acima, posso garantir que até hoje tem muita gente escrevendo cada instrução SQL em cada Query de sua aplicação.

Claro que isso não é desculpa para a equipe do infra se acomodar. QUEREMOS DISPONIBILIZAR GERAÇÃO AUTOMATICA DE SQL.

Mas um ponto legal nesta abordagem é que vc pode ter os 2 casos juntos. Ou seja, nenhum framework é capaz de gerar aquela sua instrução SQL cavernosa e ai o que vc faz, desiste de usar o framework, no Infra não, vc tem a possibilidade de escrever qualquer instrução que quiser, nao importa que instrução seja sem precisar ficar escrevendo mapeamento. E ainda vai ter a possibilidade de mapear e ter intruções sendo geradas automaticamente.

Minha idéia sobre o TTemplateReaderAuto:

1) vc faz o mapeamento das classes e atributos para tabelas e colunas via anotação no código. Claro que para aqueles que não quiserem fazer via código, pode por em um arquivo e isso ser anotado automaticamente durante a inicialização do InfraOPF

2) O esquema de carga/persistencia não mudaria em nada, a não ser que nao passariamos mais o nome do template:

  vSQLCommand := pSession.CreateNamedQuery(vObj);  <<< veja que só passei o objeto com o atributo id preenchido
  vObj := vSQLCommand.GetResult as IAccount;

3) Quando o framework pedir a instrução para o TTemplateReaderAuto será passo para ele automaticamente um
    nome padrão de template. ex:
   
    InfraOPF_SELECT, InfraOPF_DELETE, InfraOPF_UPDATE ou InfraOPF_INSERT

    Alem disso será passado tambem o typeinfo da classe a ser usada para extrair as informações (mapeamento) necessárias
    para montagem do SQL.

Vejam que será simples esta abordagem e isso vai facilitar outro recurso muito necessário que é o de Criteria (filtragem). mas isso pode ser discutido em outro tópico.

Marcos George

unread,
Apr 3, 2009, 7:16:07 AM4/3/09
to Infra - Integrated Frameworks
Bem, eu vou comentar cada ponto em um tópico separado pra não se
tornar muito confuso. Este eu gostaria de reservar apenas para o SQL
automático. Ok?

Att
Marcos George

On 2 abr, 21:05, Marcos Barreto <mrbar2...@gmail.com> wrote:
> Bem Marcos George, vou descrever aqui a minha opinião e se me permite, vou
> corrigir alguns equivocos no seu texto.
>
> Hoje temos uma hierarquia de classes responsável pela devolução de uma
> instrução SQL. A classe base chama-se hoje TTemplateReader e dela derivamos
> o TTemplateReader_IO. TTemplateReader_IO vai em um arquivo texto no hd e
> pega a instrução sql. Isso é extremamente flexível pois podemos fazer
> herança de TTemplateReader ou um de seus filhos para poder ler as instruções
> de onde quisermos. ex:
>
>    - TTemplateReaderXML - retorna a instrução SQL solicitada lida de um
>    arquivo XML;
>    - TTemplateReaderDB - retorna a instrução SQL solicitada lida do proprio
>    banco de dados da aplicação;
>    - TTemplateReaderAuto - gera a instrução SQL baseado em algum mapeamento
>    via anotação nas classes; e por ai vai
>
> Como discuti com o MG antes dele postar esta mensagem eu acho que já temos
> quase tudo que precisamos para poder fazer o TTemplateReaderAuto.
>
> E acho que nao vai mudar em quase nada na estrutura de carregamento e
> persistencia existente.
>
> Hj para carregarmos um objeto nós *PODEMOS* fazer isso, eu disse podemos por
>     *InfraOPF_SELECT, InfraOPF_DELETE, InfraOPF_UPDATE ou InfraOPF_INSERT*
Reply all
Reply to author
Forward
0 new messages