Session.Load

5 views
Skip to first unread message

Marcos George

unread,
Apr 3, 2009, 7:22:38 AM4/3/09
to Infra - Integrated Frameworks
Um novo método no Session simplificaria, e muito, as coisas (Load):

session := SessionFactory.OpenSession;
vObj := session.Load('TAccount', 10) as IAccount;

// internamente ele:
// 1. instanciaria o SqlCommand;
// 2. setaria o parametro;
// 3. efetuaria o GetResult

O novo método poderia ter vários overloads para cobrir diversas
situações

Att
Marcos George

Fabricio Colombo

unread,
Apr 3, 2009, 8:07:45 AM4/3/09
to infra...@googlegroups.com
Concordo plenamente, isso simplificaria muito. Ao invés de:
 
var
  vObj: IAccount;
  vSQLCommand: ISQLCommandQuery;
begin
  vObj := TAccount.Create;
  vObj.Id.AsInteger := 1;
  vSQLCommand := pSession.CreateNamedQuery(cLoadAccountByIDTemplateName, vObj);
  vObj := vSQLCommand.GetResult as IAccount;
 
teriamos apenas
 
var
  vObj: IAccount;
begin
  vObj := pSession.LoadByID(IAccount, [1])  as IAccount;
 
Muito mais simples e com menos código.
Dessa forma em cada situação pode-se utilizar a forma mais adequada.

Marcos Barreto

unread,
Apr 3, 2009, 12:29:37 PM4/3/09
to infra...@googlegroups.com
Um novo método no Session simplificaria, e muito, as coisas (Load):

session := SessionFactory.OpenSession;
vObj := session.Load('TAccount', 10) as IAccount;

// internamente ele:
// 1. instanciaria o SqlCommand;
// 2. setaria o parametro;
// 3. efetuaria o GetResult

Passar o nome da classe é muito passível de erros e passar um inteiro simples é muito inflexivel (o banco pode ser legado, com chave composta, etc..). acho que a melhor abordagem seria:

vObj := TAccount.Create;
vObj.Id.AsInteger := 10;
Ssession.Load(vObj) as IAccount;  // nao precisaria retornar nada o framework já preencheria o vObj

ou ainda

// nao criar a instância de TAccount e fazer
vObj := Ssession.Load(IAccount, TInfraInteger.NewFrom(10)) as IAccount;

Isso vai garantir a flexibilidade. Podemos até ter estes 2 métodos ai sobrecarregados.
Emfim, acho que ao passar um oid ele deveria ser sempre passado como um infratype.

Fabricio Colombo

unread,
Apr 3, 2009, 1:13:12 PM4/3/09
to infra...@googlegroups.com
Passar o nome da classe é muito passível de erros e passar um inteiro simples é muito inflexivel (o banco pode ser legado, com chave composta, etc..). acho que a melhor abordagem seria:

vObj := TAccount.Create;
vObj.Id.AsInteger := 10;
Ssession.Load(vObj) as IAccount;  // nao precisaria retornar nada o framework já preencheria o vObj

ou ainda

// nao criar a instância de TAccount e fazer
vObj := Ssession.Load(IAccount, TInfraInteger.NewFrom(10)) as IAccount;

Isso vai garantir a flexibilidade. Podemos até ter estes 2 métodos ai sobrecarregados.
Emfim, acho que ao passar um oid ele deveria ser sempre passado como um infratype.
 
Utilizar infratypes é melhor sim. E passar a interface em ver do nome também. Quanto a chave composta, não pode ser passado em forma de array?
 

Solerman Kaplon

unread,
Apr 3, 2009, 1:13:54 PM4/3/09
to infra...@googlegroups.com
Marcos Barreto escreveu:
Isso vai garantir a flexibilidade. Podemos até ter estes 2 métodos ai sobrecarregados.
Emfim, acho que ao passar um oid ele deveria ser sempre passado como um infratype.

Concordo plenamente. Vai funcionar tando para chaves simples quanto compostas. E ainda leva vantagem pois num aplicação real, a chave nunca vai estar fica no fonte, sempre vai vir de algum outro lugar onde potencialmente já vai estar trabalhando com types.

Solerman

Solerman Kaplon

unread,
Apr 3, 2009, 1:52:26 PM4/3/09
to infra...@googlegroups.com
Fabricio Colombo escreveu:
Utilizar infratypes é melhor sim. E passar a interface em ver do nome também. Quanto a chave composta, não pode ser passado em forma de array?

Não pois a expectativa eh ter uma classe para a chave composta com as sub-chaves dentro. Assim fica mais simples implementar caching depois pois o modelo de dados fica homogêneso. Senão, imagine tentar montar uma lista de objetos carregados que depois vão precisar ser acessados por chave e metade tem uma coluna de chave e outra parte tem N. O que se usa como índice do map?
Poderia se tentar usar array SE fosse possível instanciar a classe de OID com base nisso.

Solerman

Fabricio Colombo

unread,
Apr 3, 2009, 8:43:58 PM4/3/09
to infra...@googlegroups.com
Solerman Kaplon  escreveu:
Não pois a expectativa eh ter uma classe para a chave composta com as sub-chaves dentro. Assim fica mais simples implementar caching depois pois o modelo de dados fica homogêneso. Senão, imagine tentar montar uma lista de objetos carregados que depois vão precisar ser acessados por chave e metade tem uma coluna de chave e outra parte tem N. O que se usa como índice do map?
Poderia se tentar usar array SE fosse possível instanciar a classe de OID com base nisso.

Solerman, não entendi muito bem essa parte "Assim fica mais simples implementar caching depois pois o modelo de dados fica homogêneo". Cache do que exatamente?
 
O conceito de criar uma "subclasse" para a primary key ao meu ver não tem problema. Isso deixará os objetos normalizados, todos possuirão apenas uma propriedade que representa o OID, eliminando os problemas que vc destacou.

na prática ficaria mais ou menos assim então, certo?

IAccountPK 
  property Banco: IInfraInteger
  property Agencia: IInfraString
  property Conta: IInfraString
end;

IAccount
  ...
  property ID: IAccountPK ...
  ...
end;

Ai no load teria que criar um objeto que representa a PK e passar como parametro.
 
vObjPK := TAccountPK.Create;
vObjPK.Banco.AsInteger := 1;
vObjPK.Agencia.AsString := '437-9';
vObjPK.Conta.AsString := '142-7';
vObj := Session.Load(IAccount, vObjPK) as IAccount

ou utilizar IQL

vObj := Session.CreateQuery('from IAccount where ID.Banco = 1 and ID.Agencia = 437-9 and ID.Conta = 142-7') as IAccount;


 

Marcos Barreto

unread,
Apr 3, 2009, 10:14:03 PM4/3/09
to infra...@googlegroups.com
na prática ficaria mais ou menos assim então, certo?

Certo!  Para facilitar a definição da chave, a classe AccountPK poderia ter um método que recebesse os 3 valores!

IAccount
  property ID: IAccountPK ...
  ...
end;

vObj := TAccount.Create;   <<<<< veja que eu vou passar para o load o objeto account e nao accountpk
vObj.ID.SetValues(1, '437-9', '142-7');
vObj := Session.Load(IAccount, vObj) as IAccount

o AccountPK é tratado internamente!

Solerman Kaplon

unread,
Apr 4, 2009, 8:09:33 AM4/4/09
to infra...@googlegroups.com
Fabricio Colombo escreveu:
Solerman, não entendi muito bem essa parte "Assim fica mais simples implementar caching depois pois o modelo de dados fica homogêneo". Cache do que exatamente?

Primeiramente de todos os objetos que for dado Load. Não deve existir duas instâncias gerenciadas pela pesistência de um mesmo objeto. Se vc fizer dois load da mesma PK, o objeto retornado deverá ser o mesmo. Depois poderá vir outros níveis de cache, tal qual no hibernate há hoje.


 
O conceito de criar uma "subclasse" para a primary key ao meu ver não tem problema. Isso deixará os objetos normalizados, todos possuirão apenas uma propriedade que representa o OID, eliminando os problemas que vc destacou.

na prática ficaria mais ou menos assim então, certo?


Correto. Minha pergunta era mais com a forma de chamada do load passando os componentes da PK em array. Usando uma subclasse para PK, não se se conseguiríamos instanciar a mesma com base no array.

Solerman

Marcos Barreto

unread,
Apr 4, 2009, 8:38:03 AM4/4/09
to infra...@googlegroups.com
Primeiramente de todos os objetos que for dado Load. Não deve existir duas instâncias gerenciadas pela pesistência de um mesmo objeto. Se vc fizer dois load da mesma PK, o objeto retornado deverá ser o mesmo. Depois poderá vir outros níveis de cache, tal qual no hibernate há hoje.

Tenho algumas perguntas em relação a este cache de objetos:

1) Este cache seria único por Aplicaçao ou por Session?

2) Se por aplicação, em um ambiente distribuido, o cache estará disponível a todos os usuários?

3) Se o usuário faz uma pesquisa usando um criteria que nao seja baseado no Oid o cache nao poderia ser consultado. O que fazer nestes casos, apenas preenchemos o cache com os objetos retornados sem criar duplicidades?

4) Este esquema de cache nao aumenta a possibilidade de inconssistências (quando trabalhando no estilo client-server) pelo fato de outros terminais estarem mudando os mesmos dado tambem?

Joao Morais

unread,
Apr 5, 2009, 11:19:52 AM4/5/09
to infra...@googlegroups.com
2009/4/4 Marcos Barreto <mrba...@gmail.com>:

> Tenho algumas perguntas em relação a este cache de objetos:

Pitacos:

> 1) Este cache seria único por Aplicaçao ou por Session?

Por session.

> 2) Se por aplicação, em um ambiente distribuido, o cache estará disponível a
> todos os usuários?

Desculpa a pergunta estúpida, mas você fala em privilégio ou algo
relacionado a encapsulamento?

> 3) Se o usuário faz uma pesquisa usando um criteria que nao seja baseado no
> Oid o cache nao poderia ser consultado. O que fazer nestes casos, apenas
> preenchemos o cache com os objetos retornados sem criar duplicidades?

A pesquisa no banco deveria buscar OIDs, então o cache será usado ao
instanciar estes OIDs quando necessário.

> 4) Este esquema de cache nao aumenta a possibilidade de inconssistências
> (quando trabalhando no estilo client-server) pelo fato de outros terminais
> estarem mudando os mesmos dado tambem?

Pode acontecer com qualquer quantidade de camadas, basta dois usuários
alterando o mesmo objeto. Aí valem aqueles esquemas para evitar erguer
uma exceção sem necessidade, tal como conferir quais informações foram
alteradas em alguma camada acima (ou abaixo?) do usuário e quais o
próprio usuário alterou. Se não houver conflito, faz um merge.

Joao Morais

Solerman Kaplon

unread,
Apr 6, 2009, 1:35:33 PM4/6/09
to infra...@googlegroups.com
Marcos Barreto escreveu:
Tenho algumas perguntas em relação a este cache de objetos:

1) Este cache seria único por Aplicaçao ou por Session?


Por sessão inicialmente, mas depende do escopo da persistência. Já vi caches a nível de várias aplicações. Mas não é algo que em termos práticos seria fixo no framework, no hibernate os caches além da sessão são plugáveis (creio que parte da spec deve estar definida na JEE neste caso
)

2) Se por aplicação, em um ambiente distribuido, o cache estará disponível a todos os usuários?


Novamente, depende do deploy. Pode ser que sim, e talvez o próprio cache seja N-tier distribuído. Neste da sessão, depende da arquitetura da aplicação (está usando um servidor de aplicação ou está deixando todo mundo acessar o banco direto?).


3) Se o usuário faz uma pesquisa usando um criteria que nao seja baseado no Oid o cache nao poderia ser consultado. O que fazer nestes casos, apenas preenchemos o cache com os objetos retornados sem criar duplicidades?


Porquê não, uma vez que se o cache é baseado no que foi carregado, você pode manter uma apontamento pro objeto inteiro?
Pode muito bem pegar o resultset do SQL usado e antes de instanicar o objeto, verificar se a OID do mesmo bate com algum do cache. Em termos de load de objetos inteiro, o que você usa de critério não importa, só as informações que pede. Mas se não pediu o objeto inteiro, não estamos mais falando de algo que se aplique ao Load.



4) Este esquema de cache nao aumenta a possibilidade de inconssistências (quando trabalhando no estilo client-server) pelo fato de outros terminais estarem mudando os mesmos dado tambem?

Sempre que permitir alguém mais de uma pessoa mexendo na mesma coisa, isso pode acontecer, com ou sem cache. O cache de sessão ajuda a evitar que isso ocorra para O MESMO usuário (ex: carrega dois objetos diferentes na mesma sessão, ao se alterar um, já está inconsistente até a outra cópia ser sincronizada).

Solerman
Reply all
Reply to author
Forward
0 new messages