Muitas pessoas estão tendo problema nas coleções que contem lazy no java com a arquitetura Hibernate e flex ao comunicar com o BlazeDS, então estou com uma solução pronta para o problema de Lazy que ocorre quando o Flex comunica com o BlazeDS.
Utilizando esse componente http://sourceforge.net/projects/setlazynull/
Podemos resolver um problema que sempre ocorre no Flex ao comunicar com o java que é o problema do lazy.
Esse tipo de solução já foi colocada aki. O GraniteDS (graniteds.org) também já resolve o problema, recomendo dar uma olhada.
Depois de ver algumas soluções preferi utilizar uma camada DTO mesmo. Há replicação de código mas pelo menos não fico mandando classes de domínio para o cliente.
renzonuccitelli, essa solução é pra quem esta utilizando BlazeDS e essa do Granite eu sábia que existia então postei um plugin que faz o trabalho igual no granite mas para o blazeDS a vantagem de utilizar o BlazeDS é que é mais simples de ligar no projeto equanto o granite dá mais trabalho.
Entendi o que o projeto faz, contudo a solução não é definitiva. Se vc setar as coisas lazy para null então vc tem que indicar de alguma forma quando deseja carregar uma lista que está com inicialização preguiçosa. Pra isso eu faço uso da camada DTO. O DTO fica responsável por carregar as infos do domínio e vice-versa. Além desse mapeamento, existe a a vantagem de eu não enviar dados desnecessários ao cliente. Ex: Vc tem uma classe de dominio pessoa com vários dados, como sexo, idade, tel, cel etc. Na hora de puscar uma lista de pessoas que devo mostrar só o nome, eu crio um DTO só com o nome que faça referencia ao dominio. Assim, ao buscar uma lista, eu envio só os nomes em vez de mandar uma porção de dados que não são visualizados. Apesar de dar um trabalhinho a mais, a camanda de visualização fica mais independente do domínio.
Outra coisa que não vi mais trabalho no GraniteDS não. Para falar a verdade, ele é semelhante ao Blaze e inclusive a documentação é bem melhor, mostrando exemplos de integração com SPRING e EJB.
Outra coisa é vc reparar tb na comparação do BlazeDS com LiveCycle no Tour de Flex. Lá ele aponta que o BlazeDS não aguenta muitos usuários por CPU. Ou seja, se for para uma app grande, pode ficar inviável vc usar o BlazeDS. Adobe malandramente fazendo vc ter que pagar a “licensinha” do LiveCycle. Estou com o granite rodando no Google App Engine e até agora não tive problemas. Fica a dica de se fazer um teste de carga com o Blaze para ver se ele aguenta as pontas.
Entendi o que o projeto faz, contudo a solução não é definitiva. Se vc setar as coisas lazy para null então vc tem que indicar de alguma forma quando deseja carregar uma lista que está com inicialização preguiçosa. Pra isso eu faço uso da camada DTO. O DTO fica responsável por carregar as infos do domínio e vice-versa. Além desse mapeamento, existe a a vantagem de eu não enviar dados desnecessários ao cliente. Ex: Vc tem uma classe de dominio pessoa com vários dados, como sexo, idade, tel, cel etc. Na hora de puscar uma lista de pessoas que devo mostrar só o nome, eu crio um DTO só com o nome que faça referencia ao dominio. Assim, ao buscar uma lista, eu envio só os nomes em vez de mandar uma porção de dados que não são visualizados. Apesar de dar um trabalhinho a mais, a camanda de visualização fica mais independente do domínio.
Outra coisa que não vi mais trabalho no GraniteDS não. Para falar a verdade, ele é semelhante ao Blaze e inclusive a documentação é bem melhor, mostrando exemplos de integração com SPRING e EJB.
Outra coisa é vc reparar tb na comparação do BlazeDS com LiveCycle no Tour de Flex. Lá ele aponta que o BlazeDS não aguenta muitos usuários por CPU. Ou seja, se for para uma app grande, pode ficar inviável vc usar o BlazeDS. Adobe malandramente fazendo vc ter que pagar a “licensinha” do LiveCycle. Estou com o granite rodando no Google App Engine e até agora não tive problemas. Fica a dica de se fazer um teste de carga com o Blaze para ver se ele aguenta as pontas.
[]s[/quote]
Entendi sua posicao, mas o componente ele nao deixa acessar a colecao quando esta com lazy, no caso de nao pedir para povoar ela, eu utilizo o GraniteDS em algumas aplicações, mas tmb utilizo o blazeDS em outras e essa solução foi porque eu tive muitos problemas no lazy ao utiliza-lo, e o granite tem alguns problemas em carregar o lazy, Algumas vezes nao carregava. Poderia me mostrar um exemplo desse DTO?
Entendi o que o projeto faz, contudo a solução não é definitiva. Se vc setar as coisas lazy para null então vc tem que indicar de alguma forma quando deseja carregar uma lista que está com inicialização preguiçosa. Pra isso eu faço uso da camada DTO. O DTO fica responsável por carregar as infos do domínio e vice-versa. Além desse mapeamento, existe a a vantagem de eu não enviar dados desnecessários ao cliente. Ex: Vc tem uma classe de dominio pessoa com vários dados, como sexo, idade, tel, cel etc. Na hora de puscar uma lista de pessoas que devo mostrar só o nome, eu crio um DTO só com o nome que faça referencia ao dominio. Assim, ao buscar uma lista, eu envio só os nomes em vez de mandar uma porção de dados que não são visualizados. Apesar de dar um trabalhinho a mais, a camanda de visualização fica mais independente do domínio.
Outra coisa que não vi mais trabalho no GraniteDS não. Para falar a verdade, ele é semelhante ao Blaze e inclusive a documentação é bem melhor, mostrando exemplos de integração com SPRING e EJB.
Outra coisa é vc reparar tb na comparação do BlazeDS com LiveCycle no Tour de Flex. Lá ele aponta que o BlazeDS não aguenta muitos usuários por CPU. Ou seja, se for para uma app grande, pode ficar inviável vc usar o BlazeDS. Adobe malandramente fazendo vc ter que pagar a “licensinha” do LiveCycle. Estou com o granite rodando no Google App Engine e até agora não tive problemas. Fica a dica de se fazer um teste de carga com o Blaze para ver se ele aguenta as pontas.
[]s[/quote]
Entendi sua posicao, mas o componente ele nao deixa acessar a colecao quando esta com lazy, no caso de nao pedir para povoar ela, eu utilizo o GraniteDS em algumas aplicações, mas tmb utilizo o blazeDS em outras e essa solução foi porque eu tive muitos problemas no lazy ao utiliza-lo, e o granite tem alguns problemas em carregar o lazy, Algumas vezes nao carregava. Poderia me mostrar um exemplo desse DTO?[/quote]
Então, qual foi sua solução para indicar as listas lazy que vc queria que fossem populadas?
Entendi o que o projeto faz, contudo a solução não é definitiva. Se vc setar as coisas lazy para null então vc tem que indicar de alguma forma quando deseja carregar uma lista que está com inicialização preguiçosa. Pra isso eu faço uso da camada DTO. O DTO fica responsável por carregar as infos do domínio e vice-versa. Além desse mapeamento, existe a a vantagem de eu não enviar dados desnecessários ao cliente. Ex: Vc tem uma classe de dominio pessoa com vários dados, como sexo, idade, tel, cel etc. Na hora de puscar uma lista de pessoas que devo mostrar só o nome, eu crio um DTO só com o nome que faça referencia ao dominio. Assim, ao buscar uma lista, eu envio só os nomes em vez de mandar uma porção de dados que não são visualizados. Apesar de dar um trabalhinho a mais, a camanda de visualização fica mais independente do domínio.
Outra coisa que não vi mais trabalho no GraniteDS não. Para falar a verdade, ele é semelhante ao Blaze e inclusive a documentação é bem melhor, mostrando exemplos de integração com SPRING e EJB.
Outra coisa é vc reparar tb na comparação do BlazeDS com LiveCycle no Tour de Flex. Lá ele aponta que o BlazeDS não aguenta muitos usuários por CPU. Ou seja, se for para uma app grande, pode ficar inviável vc usar o BlazeDS. Adobe malandramente fazendo vc ter que pagar a “licensinha” do LiveCycle. Estou com o granite rodando no Google App Engine e até agora não tive problemas. Fica a dica de se fazer um teste de carga com o Blaze para ver se ele aguenta as pontas.
[]s[/quote]
Entendi sua posicao, mas o componente ele nao deixa acessar a colecao quando esta com lazy, no caso de nao pedir para povoar ela, eu utilizo o GraniteDS em algumas aplicações, mas tmb utilizo o blazeDS em outras e essa solução foi porque eu tive muitos problemas no lazy ao utiliza-lo, e o granite tem alguns problemas em carregar o lazy, Algumas vezes nao carregava. Poderia me mostrar um exemplo desse DTO?[/quote]
Então, qual foi sua solução para indicar as listas lazy que vc queria que fossem populadas? [/quote]
Seguinte, vamos supor assim um pais tem varios estados entao ficaria que no bean pais existe uma colecao de estados, por padrao ele iria vir com lazy, se vc utilizar o SetLazyNull ele estará setando null para a coleção estado quando vc faz a seguinte HQL: select * from Pais p;
desse jeito ele busca o conteudo mas a coleção fica setada null, pois se nao estivesse com o setLazyNull se vc tentar acessar esse atributo dará o erro de lazyinitializationexception. Mas porque ocorre isso? pois o blazeDS tenta acessar todos os atributos da classe no caso Pais, quando ele chega na coleção Estados e não estar utilizando o setlazyNull vai ocorrer um erro e o flex nao vai receber os dados. Caso voce queira povoar o atributo estados da classe pais é so vc fazer a seguinte HQL: select * from Pais p left join fecth p.estados est;
Assim vc carregará todas as coleções do atributo que está com lazy idependente de utilizar a anotação setlazynull.
Foi criado essa solução por motivo do BlazeDS dar um erro quando tem uma classe com atributos com lazy, me parece que ele tenta acessar esses atributos, entao unico jeito mais simples de contornar foi utilizando o setLazyNull.
Sobre as DTO pelo que andei pesquisando praticamente vc vai criar vários DTO para uma unica classe e isso gera muito arquivo.
Entendi o que o projeto faz, contudo a solução não é definitiva. Se vc setar as coisas lazy para null então vc tem que indicar de alguma forma quando deseja carregar uma lista que está com inicialização preguiçosa. Pra isso eu faço uso da camada DTO. O DTO fica responsável por carregar as infos do domínio e vice-versa. Além desse mapeamento, existe a a vantagem de eu não enviar dados desnecessários ao cliente. Ex: Vc tem uma classe de dominio pessoa com vários dados, como sexo, idade, tel, cel etc. Na hora de puscar uma lista de pessoas que devo mostrar só o nome, eu crio um DTO só com o nome que faça referencia ao dominio. Assim, ao buscar uma lista, eu envio só os nomes em vez de mandar uma porção de dados que não são visualizados. Apesar de dar um trabalhinho a mais, a camanda de visualização fica mais independente do domínio.
Outra coisa que não vi mais trabalho no GraniteDS não. Para falar a verdade, ele é semelhante ao Blaze e inclusive a documentação é bem melhor, mostrando exemplos de integração com SPRING e EJB.
Outra coisa é vc reparar tb na comparação do BlazeDS com LiveCycle no Tour de Flex. Lá ele aponta que o BlazeDS não aguenta muitos usuários por CPU. Ou seja, se for para uma app grande, pode ficar inviável vc usar o BlazeDS. Adobe malandramente fazendo vc ter que pagar a “licensinha” do LiveCycle. Estou com o granite rodando no Google App Engine e até agora não tive problemas. Fica a dica de se fazer um teste de carga com o Blaze para ver se ele aguenta as pontas.
[]s[/quote]
Entendi sua posicao, mas o componente ele nao deixa acessar a colecao quando esta com lazy, no caso de nao pedir para povoar ela, eu utilizo o GraniteDS em algumas aplicações, mas tmb utilizo o blazeDS em outras e essa solução foi porque eu tive muitos problemas no lazy ao utiliza-lo, e o granite tem alguns problemas em carregar o lazy, Algumas vezes nao carregava. Poderia me mostrar um exemplo desse DTO?[/quote]
Então, qual foi sua solução para indicar as listas lazy que vc queria que fossem populadas? [/quote]
Seguinte, vamos supor assim um pais tem varios estados entao ficaria que no bean pais existe uma colecao de estados, por padrao ele iria vir com lazy, se vc utilizar o SetLazyNull ele estará setando null para a coleção estado quando vc faz a seguinte HQL: select * from Pais p;
desse jeito ele busca o conteudo mas a coleção fica setada null, pois se nao estivesse com o setLazyNull se vc tentar acessar esse atributo dará o erro de lazyinitializationexception. Mas porque ocorre isso? pois o blazeDS tenta acessar todos os atributos da classe no caso Pais, quando ele chega na coleção Estados e não estar utilizando o setlazyNull vai ocorrer um erro e o flex nao vai receber os dados. Caso voce queira povoar o atributo estados da classe pais é so vc fazer a seguinte HQL: select * from Pais p left join fecth p.estados est;
Assim vc carregará todas as coleções do atributo que está com lazy idependente de utilizar a anotação setlazynull.
Foi criado essa solução por motivo do BlazeDS dar um erro quando tem uma classe com atributos com lazy, me parece que ele tenta acessar esses atributos, entao unico jeito mais simples de contornar foi utilizando o setLazyNull.
Sobre as DTO pelo que andei pesquisando praticamente vc vai criar vários DTO para uma unica classe e isso gera muito arquivo.[/quote]
Entendi, então vc acaba tendo que indicar na Query os campos que vc carregar. No meu projeto eu estou usando o Google App Engine com o Big Table e não existe essa opção lá. Realmente só safei com o DTO. Com certeza gera muitos arquivos os DTOs, mas vc não manda seu domínio todo para o cliente. Mandar o domínio todo pode até ser uma falha de segurança, dependendo da app. Ex: Trabalho com protuário universal em minha empresa. Sendo assim, existem dados de saúde confidenciais. Dependendo da classe de domínio, vc não pode enviar todos os dados para o cliente, correndo risco de expor informação alheia.
Mas foi muito bom vc colocar a solução aki. Antigamente eu resolvia isso colocando um filtro que setava o campo para null quando recebia o LazyException. Cheguei a postar aki a solução.
humbertopatrick estou fazendo meu TCC com o tema sobre a comunicação Java + Flex utilizando o BlazeDS
e hoje coincidentemente estava escrevendo sobre o Lazy-Loading do hibernate que não obtive sucesso em utiliza-lo
poderia melhor explicar como utilizar essa API e o que realmente ela faz?
[quote=Two_]humbertopatrick estou fazendo meu TCC com o tema sobre a comunicação Java + Flex utilizando o BlazeDS
e hoje coincidentemente estava escrevendo sobre o Lazy-Loading do hibernate que não obtive sucesso em utiliza-lo
poderia melhor explicar como utilizar essa API e o que realmente ela faz?
[/quote]
Two_, O SetLazyNull ajuda a corrigir o erro do lazy loading que acontece com o BlazeDS ao fazer a comunicação entre o Java com o Flex, quando uma classe que é uma entidade do banco que contém uma coleção de objetos (um para muitos), essa coleção por padrão vem como lazy, quando vc manda o java fazer uma consulta ao banco através do hibernate ele carrega os dados do banco nessa classe, então o BlazeDS pega essa informação e devolve para o Flex, mas no momento de devolver o BlazeDS faz uma varredura nessa classe, nesse momento quando ele passa no atributo que é uma coleção faz disparar o LazyInitialization fazendo o blazeDS pensar que isso foi um erro e devolvendo para o flex um erro sem trazer os dados consultados, então o papel do SetLazyNull é pegar onde tiver uma coleção do tipo lazy e setar null, mas quando ele estiver carregado essa coleção ele não seta Null.
[quote=Two_]humbertopatrick estou fazendo meu TCC com o tema sobre a comunicação Java + Flex utilizando o BlazeDS
e hoje coincidentemente estava escrevendo sobre o Lazy-Loading do hibernate que não obtive sucesso em utiliza-lo
poderia melhor explicar como utilizar essa API e o que realmente ela faz?
[/quote]
Two_, O SetLazyNull ajuda a corrigir o erro do lazy loading que acontece com o BlazeDS ao fazer a comunicação entre o Java com o Flex, quando uma classe que é uma entidade do banco que contém uma coleção de objetos (um para muitos), essa coleção por padrão vem como lazy, quando vc manda o java fazer uma consulta ao banco através do hibernate ele carrega os dados do banco nessa classe, então o BlazeDS pega essa informação e devolve para o Flex, mas no momento de devolver o BlazeDS faz uma varredura nessa classe, nesse momento quando ele passa no atributo que é uma coleção faz disparar o LazyInitialization fazendo o blazeDS pensar que isso foi um erro e devolvendo para o flex um erro sem trazer os dados consultados, então o papel do SetLazyNull é pegar onde tiver uma coleção do tipo lazy e setar null, mas quando ele estiver carregado essa coleção ele não seta Null. Para utilizar o SetlazyNull no método que vai fazer a busca do conteúdo é só adicionar a anotação @LazyNull em cima do método que faz a busca dos dados ex:
@LazyNull
public Estado buscarEstados(Integer id){....}
Fazendo assim ele resolve o problema do lazy.
Me parece uma solução parcial para o caso do Lazy. A utilização de API propria para essa função como o dphibernate(http://code.google.com/p/dphibernate/)
não conseguir implementar pela complexidade e falta de documentação da mesma. Utilizo o Spring para gerenciar o hibernate e essa solução me pareceu simples.
Eu estava utilizando um filtro do Spring parecido com com a ação dessa Api simples que vc indicou, mais que não funcionou do modo esperado na aplicação, pois tudo passava por esse filtro que setava sempre Null para as exceções do tipo Lazy do hibernate.
Vou testar e coloco o resultado aqui.
Two_, essa API foi eu quem desenvolvi, ela está na primeira versão então caso vc tiver alguma opinião para fornecer acho legal para que eu posso implementar nas próximas versões. Fico aguardando a sua colocação sobre a API, mas qualquer dúvida pode postar que eu responderei.
Muita gente falando desse assunto (lazyloading)
Eu mais uma vez digo "não tive problemas usando o BlazeDS (usando EclipseLink),
mas dá um problemão de performance em relações do tipo NxN (com muitos registros, claro),
fica inviável.
E eu tava pensando em testar (tb) o Granite, e ao mesmo tempo, bastante inclinado a usar
DTOs mesmo, e pelo que vi, até quem usa o Granite optou pelo DTO, talvez seja mais "fácil"
do que ficar procurando dificultar
[quote=UpTheIrons]Muita gente falando desse assunto (lazyloading)
Eu mais uma vez digo "não tive problemas usando o BlazeDS (usando EclipseLink),
mas dá um problemão de performance em relações do tipo NxN (com muitos registros, claro),
fica inviável.
E eu tava pensando em testar (tb) o Granite, e ao mesmo tempo, bastante inclinado a usar
DTOs mesmo, e pelo que vi, até quem usa o Granite optou pelo DTO, talvez seja mais "fácil"
do que ficar procurando dificultar :)[/quote]
A respeito de utilizar o granite pode ser uma opção boa, mas o problema de ter uma performace mais baixa não é a respeito do hibernate ou eclipselink, deve ser outro problema pois eu utilizo o hibernate em aplicações que contem alto trafego de dados e alto conteudo de registro no banco, onde o sistema faz consultas que trazem dados muito cabulosas, e a performace é otima, entao pode ser algum problema. Em utilizar o DTO não pode ser uma alternativa muito legal, mas caso vc não encontre outra opção não vejo o porque de nao utilizar o DTO. O unico problema do granite que vejo é a configuração acho muito trabalhoso. Mas fica a criterio seu, o unico proposito meu é resolver o problema do lazy como criei essa solução e ela ainda esta na versão 1.0 pois só funciona no hibernate, caso vcs tirerem outras ideias como eu ja disse pode passando por aki que vou implementando na API e ja esta anotado para funcionar no eclipselink.
Aqui n tem jeito.
Tenho duas entidades CONTA e TIPO … e há uma tabela associativa CONTA_TIPO
Se fecho dos dois lados, um relacionamento NxN, a performance cai significativamente,
se quebro a relação de um dos lados, a coisa funciona como eu desejaria.
E agora surgiu outro problema, em ambas as situações, qdo atualizo o registro da tabela
CONTAS, o registro equivalente na tabela CONTA_TIPO é excluído, pqp!, mas essa é outra
questão, vou ver aqui.
Mas tá osso!
Mas fiquei curioso com o q disse:
[quote]
utilizo o hibernate em aplicações que contem alto trafego de dados e alto conteudo de registro no banco, onde o sistema faz consultas que trazem dados muito cabulosas, e a performace é otima[/quote]
Usando Flex, tem consultas NxN com muuuitos dados?!
Adobe Flex foi desenvolvido para corresponder ao mercado empresarial, sendo para simples sites ou para grandes empresas e, normalmente utilizado no ultimo caso citado.
Em relação ao NxN do hibernate também nunca tive problema em desempenho, nem ao menos NxN com atributo.
Talvez seja código mal escrito não?
[quote=UpTheIrons]Aqui n tem jeito.
Tenho duas entidades CONTA e TIPO … e há uma tabela associativa CONTA_TIPO
Se fecho dos dois lados, um relacionamento NxN, a performance cai significativamente,
se quebro a relação de um dos lados, a coisa funciona como eu desejaria.
E agora surgiu outro problema, em ambas as situações, qdo atualizo o registro da tabela
CONTAS, o registro equivalente na tabela CONTA_TIPO é excluído, pqp!, mas essa é outra
questão, vou ver aqui.
Mas tá osso!
Mas fiquei curioso com o q disse:
[quote]
utilizo o hibernate em aplicações que contem alto trafego de dados e alto conteudo de registro no banco, onde o sistema faz consultas que trazem dados muito cabulosas, e a performace é otima[/quote]
Usando Flex, tem consultas NxN com muuuitos dados?![/quote]
Se o seu banco foi criado pelo próprio Hibernate, toma cuidado que algumas vezes ele não cria os índices nos bancos para as FK´s. Só de colocar os índices já melhora consideravelmente.
A solução até agora foi ter tirado o relacionamento em uma das pontas (no jpa, n no banco)… gambiarra feia, eu sei,
mas por enqto foi a solução, do jeito q tava, tava impraticável.