Bom, no blog da Caelum a um tempo atras fizeram um POST sobre um DAO genérico, meio bizarro …
Bom, eu uso um DAO genérico a algum tempo, mas o meu DAO genérico tm algumas features a mais do que o mostrado no post da caelum …
Neste exemplo eu ja deixo os metodos para fazer um query by example prontinho, usando a API de criteria do Hibernate …
bom, chega de enrolação, vamos a alguns exemplos …
primeiro, crio uma interface para este DAO …
package br.com.techoffice.site.dao;
import java.io.Serializable;
import java.util.List;
public interface TOBaseDao<T, PK extends Serializable> {
public Class getObjectClass();
public T save(T object);
public T load(PK primaryKey);
public T get(PK primaryKey);
public List listAll();
public List findByExample(final T example);
public T findOneByExample(final T example);
public List listAll(final int first,final int max);
public int listAllPageCount();
public List findByExample(final T example,final int first,final int max);
public int findByExamplePageCount(final T example);
public void update(T object);
public void delete(T object);
public void rebind(T object);
}
onde o método getObjectClass() deve retornar a classe de trabalho deste DAO, a mesma passada no parâmetro T quando a interface for estendida …
e a implementação desta interface, fica mais ou menos assim:
package br.com.techoffice.site.dao.impl; import java.io.Serializable; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hibernate.Criteria; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.criterion.Example; import org.hibernate.criterion.MatchMode; import org.hibernate.criterion.Example.PropertySelector; import org.hibernate.type.Type; import org.springframework.orm.hibernate3.support.HibernateDaoSupport; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import br.com.techoffice.site.dao.TOBaseDao; import br.com.techoffice.site.dao.TODaoListener; @Transactional(propagation = Propagation.REQUIRED, timeout = 20) public abstract class TOBaseHibernateDaoextends HibernateDaoSupport implements TOBaseDao<T, PK>, PropertySelector { private static final Log logger = LogFactory.getLog(TOBaseHibernateDao.class); private final Class objectClass; public TOBaseHibernateDao(final Class objectClass) { this.objectClass = objectClass; } @SuppressWarnings("unchecked") public Class getObjectClass() { return objectClass; } public int findByExamplePageCount(final T example) { final List l = findByExample(example); final Integer i = new Integer(l.size()); return i.intValue(); } public int listAllPageCount() { final List l = listAll(); final Integer i = new Integer(l.size()); return i.intValue(); } /* * (non-Javadoc) * * @see br.ufrgs.hcpa.template.dao.GetNetBaseDao#findOneByExample(T) */ public T findOneByExample(final T example) { final List res = findByExample(example, 0, 1); if ((res != null) && (res.size() == 1)) { return res.get(0); } else { return null; } } public T save(final T object) { try { final Session s = getSession(false); s.save(object); s.flush(); return object; } catch (final HibernateException ex) { TOBaseHibernateDao.logger.error(ex); throw convertHibernateAccessException(ex); } } public void update(final T object) { try { final Session s = getSession(false); s.update(object); s.flush(); } catch (final HibernateException ex) { TOBaseHibernateDao.logger.error(ex); throw convertHibernateAccessException(ex); } } public void rebind(final T object) { try { getSession(false).refresh(object); } catch (final HibernateException ex) { TOBaseHibernateDao.logger.error(ex); throw convertHibernateAccessException(ex); } } public void delete(final T object) { try { getSession(false).delete(object); } catch (final HibernateException ex) { TOBaseHibernateDao.logger.error(ex); throw convertHibernateAccessException(ex); } } @SuppressWarnings("unchecked") public T load(final PK primaryKey) { try { final Session s = getSession(false); final Object o = s.load(objectClass, primaryKey); return (T) o; } catch (final HibernateException ex) { TOBaseHibernateDao.logger.error(ex); throw convertHibernateAccessException(ex); } } @SuppressWarnings("unchecked") public T get(final PK primaryKey) { try { final Session s = getSession(false); final Object o = s.load(objectClass, primaryKey); return (T) o; } catch (final HibernateException ex) { TOBaseHibernateDao.logger.error(ex); throw convertHibernateAccessException(ex); } } @SuppressWarnings("unchecked") public List listAll() { try { final Session s = getSession(false); final Criteria c = s.createCriteria(objectClass); addOrderToCriteria(c); return c.list(); } catch (final HibernateException ex) { TOBaseHibernateDao.logger.error(ex); throw convertHibernateAccessException(ex); } } @SuppressWarnings("unchecked") public List findByExample(final T example) { try { final Session s = getSession(false); final Criteria c = s.createCriteria(objectClass); c.add(Example.create(example).enableLike(MatchMode.ANYWHERE).ignoreCase().setPropertySelector(this)); addOrderToCriteria(c); addPropertiedToCriteria(c, example); return c.list(); } catch (final HibernateException ex) { TOBaseHibernateDao.logger.error(ex); throw convertHibernateAccessException(ex); } } protected void addPropertiedToCriteria(final Criteria c, final T example) { } @SuppressWarnings("unchecked") public List findByExample(final T example, final int first, final int max) { try { final Session s = getSession(false); final Criteria c = s.createCriteria(objectClass); c.add(Example.create(example).enableLike(MatchMode.ANYWHERE).ignoreCase().setPropertySelector(this)); addPropertiedToCriteria(c, example); addOrderToCriteria(c); if (first != 0) { c.setFirstResult(first); } if (max != 0) { c.setMaxResults(max); } return c.list(); } catch (final HibernateException ex) { TOBaseHibernateDao.logger.error(ex); throw convertHibernateAccessException(ex); } } @SuppressWarnings("unchecked") public List listAll(final int first, final int max) { try { final Session s = getSession(false); final Criteria c = s.createCriteria(objectClass); addOrderToCriteria(c); if (first != 0) { c.setFirstResult(first); } if (max != 0) { c.setMaxResults(max); } return c.list(); } catch (final HibernateException ex) { TOBaseHibernateDao.logger.error(ex); throw convertHibernateAccessException(ex); } } protected void addOrderToCriteria(Criteria c) { } public boolean include(Object propertyValue, String propertyName, Type type) { if((propertyValue!=null) && (propertyValue instanceof String)){ return !"".equals(((String)propertyValue).trim()); } return propertyValue!=null; } }
onde o método addOrderToCriteria, permite que subclasses deste DAO ordenem as consultas …
o método addPropertiedToCriteria permite que subclasses adicionem propriedades não incluidas pelo hibernate nas consultas …
e o método include combinado com o setPropertySelector da classe Example é uma melhoria adicionada a pouco tempo, que faz o mesmo que o addPropertiedToCriteria, mas de forma automática, ou seja, inclui as propriedades PK e FK também na QBE …
…
Bom, depois disto tudo, só falta criar o DAO para alguma entidade persistida pelo Hibernate, como por exemplo uma classe Curriculo …
Criamos a interface do nosso DAO:
package br.com.techoffice.site.dao; import br.com.techoffice.site.data.Curriculo; public interface CurriculoDao extends TOBaseDao{ }
e logo depois a implementação deste DAO:
package br.com.techoffice.site.dao.impl; import net.java.dev.springannotation.annotation.Bean; import br.com.techoffice.site.dao.CurriculoDao; import br.com.techoffice.site.data.Curriculo; @Bean(name="curriculoDao") public class CurriculoDaoImpl extends TOBaseHibernateDaoimplements CurriculoDao { private static final long serialVersionUID = 1L; public CurriculoDaoImpl() { super(Curriculo.class); } }
acho que era isto, o que acharam deste DAO genérico?
pela minha experiência, ele resolve de maneira estupidamente fácil em torno de 60% dos meus problemas de persistencia, nos outros 40% ai é necessário criar algum outro metodo de pesquisa especializado para cada situação …
mas acho que é esta a ideia das coisas genéricas, facilitar a maior parte do trabalho e permitir que a menor parte seja feita com um pouquinho de trabalho extra
o que vocês acham?
Tags: Java
PERFEITO ESSE DAO!
Urubatan muito bom post. Muito bem explicado!!!
Parabens amigo!!!
Urubatan eu tinha visto este seu DAO num workshop no webdays, ficou muito bom mesmo …..
Parabéns pelo trabalho que vem realizando pela comunidade, há algum tempo acompanho, então resolvi deixar meu recado…
Opa Uburatan ta show esse dao genérico, parabéns.
Tenho umas duvidas simples.
esse Propagation.REQUIRED está dizendo que a transação é obrigatória para todos os métodos? aquele mesmo esquema quando declarado via xml?
E a respeito do include ai, você explicou mas eu fiquei viajando, poderia explicar de outra forma ou passar algum link?
Como você está utilizando o HibernateDaoSuport, teria alguma vantagem se utilizasse o método getHibernateTemplate() e/ou utilizar aquele esquema da interfacer HibernateCallback ?
Uma correção besta é que no método get está utilizando load ou invés de get.
Valeus Gécen
Thiago,
o Propagation.REQUIRED é do spring, e sim, quando ele esta anotando uma classe diz que todos os metodos requerem uma transação …
quanto ao include, o esquema é que o QueryByExample do Hibernate não inclui campos de relacionamento e PKs, aquele include é chamado quando eu chamo
[java]
Example.create(example).enableLike(MatchMode.ANYWHERE).ignoreCase().setPropertySelector(this)
[/java]
ou seja, é o callback do property selector do hibernate apenas …
e quanto a HibernateTemplate X convertHibernateAccessException(ex);
uso a segunda opção por que acho mais bonito só, mas não vejo nenhuma razão concreta para usar uma ou a outra abordagem …
Olá Urubatan, entendi agora, vlw.
Só mais uma duvida.
E a respeito do objectClass que é passado como construtor das classes concretas, ele é realmente preciso já que estamos passando o tipo via generics? eu vi no blog da caleum um artificio que não precisaria dessa classe, conforme no link abaixo:
http://blog.caelum.com.br/2006/10/29/brincando-com-generics-o-bizarregenericdao/
o que você acha dessa solução?
Eu tb escrevi um pouco sobre a classe que é passada no construtor (ou melhor, sobre a ‘mágica’ necessária pra eliminá-lo): http://javapub.blogspot.com/2006/12/generics-reflection-hierarquias-de.html
No fim, eu achei melhor manter essa passagem por parâmetro do que me aventurar nessa zona obscura
Oi,
O dao ficou muito bom. Gostaria de saber se você não acha mais interessante algo como “return listAll().size()” no lugar de instanciar um Integer nos métodos de page count?
Abraços
realmente seria melhor …
não lembro por que esta implementado desta forma, deve ter ficado assim em alguma das metamorfoses sofridas por este DAO durante o tempo de vida dele e eu não prestei atenção :S
Vaoeu a dica
Legal, muito boa implementação, existiria alguma forma de injetar o objectClass pelo Spring?
Urubatan, por curiosidade, porque você chama o flush() após o save() e update()?
sim, é possivel injetar o objectClass pelo spring …
e diego, eu realmente não lembro o por que do flush, acho que no projeto em que eu fiz isto, estava dando algum bug de batch update e eu tentei resolver assim antes de desabilitar o batch update do hibernate …
Muito bom o DAO
So uma duvida… nao seria melhor ter uma classe de negocio e colocar a anotacao dizendo que é requirido uma trasacao nela
por exemplo:
@Transactional(propagation = Propagation.REQUIRED, timeout = 20)
public class ContaCorrente(){
public retirar(){
ContaDAO conta = factory.getContaDAO();
UsuarioDAO usuario = factory.getUsuarioDAO();
…
}
}
assim todos os DAOs estariam dentro de uma mesma transacao… eu faco uma implementacao assim
A vantagem desta abordagem é que a configuração mais externa é a que vale.
por exemplo, estou dizendo que os metodos do DAO requerem uma transação, isto não quer dizer uma transação nova …
por tanto, se no business, o metodo necessitar de uma transação, sera criada uma transação para aquele metodo, e todas as chamadas de dao de dentro daquele metodo utilizarão a mesma transação, por tanto, todas as chamadas estarão dentro da mesma transação …
assim a transação sera maior, e ainda assim atomica.
mas caso o metodo do business não precisar de uma transação, serão criadas pequenas transações para cada chamada a um metodo de um DAO.
ou seja, fica valendo a maior transação
Olá Urubatan, primeiramente parabéns pelo trabalho, tenho uma dúvida sobre transação.
Por exemplo em uma transação em que eu tenha q inserir dados de uma nova venda e dados de itens dessa venda, essa implementação do Dao genérico contempla esse tipo de situação ou tenho que fazer isso por fora.
inicio da transacao
…
daoVenda.salvar(venda);
daoItens.salvar(itens);
…
fim da transacao
algo onde a transação deveria ser mais ou menos assim, um exemplo tosco só para ter um idéia.
Mais uma vez parabéns pela iniciativa.
Mário, da uma olhada no meu comentário anterior que explica exatamente isto …
Beleza, pensei que com objetos de dao’s diferentes ele fazia diferentes transacoes.
Valeu.
Ola
Copiando o que vc escreveu:
A vantagem desta abordagem é que a configuração mais externa é a que vale.
por exemplo, estou dizendo que os metodos do DAO requerem uma transação, isto não quer dizer uma transação nova
Gostaria de saber como vc fez para trabalhar com essa abordagem, o seu artigo explica detalhes de como funciona o DAO generic, que por sinal é muito bom, mas nao explica como fazer o controle de transação. Vc tem algum material explicando como fazer ?
Obrigado.
Ronildo, desculpe a demora na resposta, não tinha visto a pergunta …
o controle de transações funciona exatamente como em um session bean com CMT, ou seja, vale a transação de maior escopo …
demarcação para a classe vale para todos os métodos
demarcação no método sobre escreve a da classe
e se tem todas as opções de propagação de transações que existem nos EJBs.
mais informações sobre isto na documentação dos EJBs ou na documentação do spring
Urubatan, gostei da sua implementação do TOBaseHibernateDao e passei a utilizar algo bem semelhante como base para meus Daos.
Utilizo também uma factory para os Daos, mas estou com um problema com as transações:
Erro: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
Pesquisei bastante sobre isso, mas não encontrei uma solução. Consigo fazer com o funcione se chamar getSession(true), isto é, permitindo que uma transação seja criada nesse momento, o que não é recomendado, pelo que li.
Como você configura seu applicationContext para usar essa implementação?
Outra dúvida, relativa à pergunta do Mário Dantas: como eu consigo começar e finalizar uma transação “por fora” dos Daos, já que eles não expõe os métodos relativos à session?
Dê uma conferida aqui Lucas.
http://pastebin.co.uk/13149
Valeu Thiago! Havia encontrado algo semelhante aqui uns minutos antes de você postar e me deparei com outro erro. Usei o que você postou (achei melhor do que o que eu havia encontrado, pois especifica mais níveis de isolamento).
Porém, agora estou com outro erro…
Faço um listAll() numa classe Cliente. Essa classe possui uma Collection com lazy loading. Para buscar os clientes dá tudo certo. Porém, quando tento iterar pela coleção de pedidos:
Exception in thread "main" org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.lecom.tecnologia.model.Cliente.pedidos, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:358)
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:350)
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:343)
at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:86)
at org.hibernate.collection.PersistentSet.iterator(PersistentSet.java:163)
at com.lecom.tecnologia.main.Tester.test(Tester.java:29)
at com.lecom.tecnologia.main.Main.main(Main.java:17)
Pelo jeito a sessão está sendo “perdida”. O logger me retorna algumas coisas relacionadas a isso (após selecionar os clientes com sucesso):
DEBUG [main] (TransactionAspectSupport.java:305) - Completing transaction for [com.lecom.tecnologia.dao.IGenericDao.listAll]
DEBUG [main] (AbstractPlatformTransactionManager.java:819) - Triggering beforeCommit synchronization
DEBUG [main] (AbstractPlatformTransactionManager.java:832) - Triggering beforeCompletion synchronization
DEBUG [main] (TransactionSynchronizationManager.java:190) - Removed value [org.springframework.orm.hibernate3.SessionHolder@3b4b1e] for key [org.hibernate.impl.SessionFactoryImpl@c0a9f9] from thread [main]
DEBUG [main] (AbstractPlatformTransactionManager.java:845) - Triggering afterCommit synchronization
DEBUG [main] (AbstractPlatformTransactionManager.java:861) - Triggering afterCompletion synchronization
DEBUG [main] (SessionFactoryUtils.java:781) - Closing Hibernate Session
DEBUG [main] (TransactionSynchronizationManager.java:272) - Clearing transaction synchronization
Alguma idéia?
Ai nesse caso, você tem que carregar a coleção de pedidos antecipadamente, pois quando você tenta acessa-la a sessão já foi fechada por isso da o lazy.
Vai lá na documentação do hibernate e procura sobre fetch, você pode setar no seu mapeamento como default para sempre carregar a coleção, ou no metodo que estiver realizando a query, via criteria ou hql, especificar se deve carregar ou não.
Pois é, nas buscas que eu fiz encontrei isso mesmo. Ele fecha a sessão após cada transação, então ao tentar pegar a lista de pedidos vai dar erro pois já é outra sessão…
A minha dúvida é: por esse motivo perco o benefício de desempenho que ganho com o lazy loading? Não há outro jeito a não ser fazer a query novamente utilizando left join fetch?
ùma solução para isto é se você estiver utilizando Hibernate sem o spring (o que parece por causa da factory que você mencionou) mudar na configuracão do hibernate para managed sessions, assim você cria e destroi as sessions.
caso esteja utilizando o spring utilize algo parecido com isto:
[java]
SessionHolder sessionHolder =
(SessionHolder) TransactionSynchronizationManager.getResource(getSessionFactory());
if(sessionHolder==null){
TransactionSynchronizationManager.bindResource(getSessionFactory(),new SessionHolder(getSessionFactory().openSession());
}[/java]
não se esqueça que fazendo isto você é o responsável por fechar a sessão também …
PS.: eu achei muito legal outro visitante do blog responder uma duvida em um comentário
Muito obrigado Thiago.
Muito legal a inciativa do Thiago mesmo.
Urubatan, estou usando o Spring sim. É uma prática ruim usar uma DaoFactory com Spring?
Não tenho o código agora, está no trabalho, mas fiz mais ou menos o seguinte:
Uma interface genérica, semelhante a sua TOBaseDao.
Uma classe abstrata com a implementação dessa interface para o hibernate, como a classe TOBaseHibernateDao.
Uma interface genérica para a DaoFactory, com métodos como: public IClienteDao getClienteDao;
Uma interface e implementação para cada Dao, onde posso colocar métodos específicos.
A implementação da factory possui os atributos (as interfaces dos Daos) que são injetadas via método set pelo Spring.
Nas classes que consomem os Daos, tenho apenas a interface da factory como atributo e a implementação é injetada pelo Spring.
Obrigado pelo retorno, vou tentar isso no trabalho amanhã (trabalho da faculdade hoje =/ ).
Sobre a minha segunda pergunta no primeiro post, alguma orientação? A mais óbvia que vejo seria colocar dentro de um Dao chamadas a outros, fazendo tudo na transação do primeiro, mas acho que isso não é muito bom…
Como não quero ter que controlar a sessão, fiz o seguinte: antes de acessar a coleção de pedidos, uso o método clienteDao.rebind(cliente). Agora ele usa uma transação para buscar os clientes e depois uma transação para buscar cada lista de pedidos. Funciona, mas achei bem feio…
De acordo com o que pesquisei, o padrão OpenSessionInView resolve isso, está correto?
esta solução do rebind funciona também
mas prende o teu código a api do Hibernate se isto não estiver sendo feito dentro de um DAO.
se bem que não é exatamente um problema prender o código a API do Hibernate
PS.: o OpenSessionInView também resolve isto …
Urubatan, como você costuma contornar essa situação? Ou você não utiliza lazy loading?
Opa, vlw pessoal.
Eu não custumo utilizar muito lazy loading, pelo menos no projeto no qual estou envolvido.
Como utilizo ajax, via DWR, quando realizo as consultas geralmente trago tudo que eu quero, como o sistema não lida com grande volume de dados creio que não tem problemas, fora que realizo paginações para trazer uma quantidade limitada de dados.
Lucas, eu uso lazy bastante e como a maior parte das apps é web, o OpenSessionInView ja resolve o meu problema …
quando trabalho com ajax procuro não utilizar as mesmas entidades (hoje estou fazendo isto e estou transformando em HashMaps os valores transferidos via ajax.
e quando o OpenSessionInView não resolve, como esta semana que tive que implementar um wizard com a sessão aberta durante todo o wizard, eu copiei o OpenSessionInView filter do Spring, e fiz com que quando eu estivesse no wizard, ele armazenasse a session na HttpSession e usando um código parecido com:
[java]
SessionHolder sessionHolder =
(SessionHolder) TransactionSynchronizationManager.getResource(getSessionFactory());
if(sessionHolder==null){
TransactionSynchronizationManager.bindResource(getSessionFactory(),new SessionHolder(getSessionFactory().openSession());
}
[/java]
ele enquanto ainda no wizard, recuperasse a sessão do HttpSession e utilizasse a mesma durante todo o wizard
mas como sempre, a solução mais apropriada, depende de cada situação
Legal… por enquanto estou apenas testando o Spring com Hibernate, então estou escrevendo uma aplicação console mesmo. Esse “esquema” do SessionHolder funcionou bem, apenas adicionei o “unbinding” antes de finalizar a aplicação:
TransactionSynchronizationManager.unbindResource(this.sessionFactory);
SessionFactoryUtils.releaseSession(session, this.sessionFactory);
Estou fazendo uma aplicação também em .NET com NHibernate e lá costumo colocar a session no HttpSession também… funciona =D
Alguma opinião sobre a minha implementação com factory? Estive pensando: seria bom eu configurar os beans dos Daos como lazy-init? Acho que seria uma boa, já que na factory eu tenho a injeção de todos os Daos, mas não vou utilizar todos sempre.
bom, sobre a factory …
containers IoC foram criados para que ninguem mais utilizasse factories …
por tanto, ou tu utiliza o spring ou a tua dao factory, não as duas coisas junto …
mas esta é só a minha opinião
Sim, faz sentido… na verdade essa factory não tá criando nada, ela apenas retorna os daos que são injetados, então ela acaba perdendo a semântica de criadora, passando a ser apenas um objeto agregador, ou seja, acaba não sendo uma factory de verdade.
Vi muita gente usando Spring e Castle Windsor (container IoC pra .NET) com essa “factory”, então acabei fazendo da mesma forma. Vou procurar saber mais sobre isso.
Obrigado pela ajuda!
Olá Urubatan,
Primeio gostaria de parabenizar pelo DAO genérico que vc construi. Desenvolvi um dao bem parecido com esse aí, só que o único problema aí é que tenho que criar uma classe dao concreta para todas as minhas classes persistíveis.
Há alguma forma de isso não ser necessário?
é só alterar ele para passar o objectClass como parametro para o método que precisar dele
Olá,
Muito bom seu artigo!!
So fiquei com uma dúvida:
E se eu quisesse que uma classe CurriculoDireito que estende Curriculo tivesse também um DAO que extendesse o DAO de Curriculo, como proceder?
public interface CurriculoDAO extends TOBaseDao{
public List getCurriculosByName();
}
Estou batendo a cabeça aqui mas não acho solução.
public interface CurriculoDireitoDAO extends CurriculoDAO {
// este deve ser implicito
// public List getCurriculosByName();
public List getCurriculoEstruturaDireito();
}
é uma sugestão meio tosca, mas o que eu gostaria era de poder Herdar os metodos das interfaces dos DAOs..
Postei uma dúvida sobre isso no GUJ, e me direcionaram para seu blog
http://www.guj.com.br/posts/list/66036.java
se você tiver alguma idéia, seria muito grato.
vlw
Abraços e parabéns!
não entendi a dúvida …
este DAO genérico não atrabalha em nada a utilização de herança …
para dar um exemplo de um blog
Urubatan, poderia me explicar como funciona exatamente este método…
public List findByExample(final T example, final int first, final int max)
Urubatan…
esse “T” quer dizer o que mesmo ?que é um tipo indefinido ?
alexandre, isto é a sintaxe de generics do Java 5
ola urubatan.
sobre sua primeira classe TOBaseDao
certez
ola urubatan.
sobre sua primeira classe TOBaseDao
bom, como ela implementa classe Generic sem receber o parametro
TOBaseDao
essa e minha duvida !
abs.
Algum exemplo sem utilizar spring? com struts 2
Achei bem legal essa classe, muito útil também.
Sobre os métodos para contar regitros, fico meio preocupado, pois caso a tabela seja muito grande, todos os registros serão carregados?
Não teria como fazer uma verificação só da qtde, como faríamos com o SQL (select count(*) from tabela)?
Valeu
Meio tarde mas se ajudar ainda:
Fabio em uma entidade se vc mapear ela com
@LazyCollection(LazyCollectionOption.EXTRA)
O hibernate fica mais esperto no carregamento lazy, se vc der somente um size(), ele ira dar um count, tambem fica mais esperto quanto ao contains, verifica pelo banco em vez de carregar a lista e verificar em memoria.
Olá Urubatan,
Eu utilizo hibernate(jpa) com um dao genérico e funciona perfeitamente, exceto quando tento inserir uma entidade que herda outra entindade abstrata.
Eu uso apenas um dao para todas as entidades filhas e por padrão o dao recebe o .class da entidade pai. Isto funciona perfeitamente para consultas polimórficas, porém ao inserir as classes filhas apenas os atributos herdados são persistidos.
É possível fazer uma inserção “polimórfica” através do dao da entidade pai?
é possível sim, provavelmente você esqueceu de colocar o @Entity nas classes filhas
Valeu!!!
Eu já havia corrigido o problema e realmente era uma anotação da classe.
Na anotação @Column de um atributo eu coloquei insertable=false, por pensar que funcionava de outra forma.
Depois que arrumei funcionou corretamente.
Desculpe minha falta de informação, mas não entendi como utilizar esta implementação, para cada classe minha cliente, produto vou ter que implementar um DAO? gostaria de fazer um classe generica onde passar o objeto e lá dentro tratar tudo generico pelo que vi este exemplo faz isso, mas não entendi como utilizar esta interface será que alguém poderia dar um exemplo de como instanciar um objeto utilizando esta implemenação?