DAO generico com Spring

Pessoal,

Tenho uma interface genérica e uma implementação generica com hibernate para meus DAOs. Não gostaria de escrever para da um dos meus DAOs a classe extendida dessa implementação do hibernate generica. Uma solução seria mapear inumeros no meu applicationContext.xml

<bean id="culturaDao" class="br.al.gov.seagri.persistencia.dao.GenericDaoHibernateImpl">
		<constructor-arg>
			<value>br.al.gov.seagri.dominio.Cultura</value>
		</constructor-arg>
		<property name="sessionFactory" ref="sessionFactory"/>
	</bean>
	
	<bean id="propriedadeDao" class="br.al.gov.seagri.persistencia.dao.GenericDaoHibernateImpl">
		<constructor-arg>
			<value>br.al.gov.seagri.dominio.Propriedade</value>
		</constructor-arg>
		<property name="sessionFactory" ref="sessionFactory"/>
	</bean>
.........

São muitos DAOs, gostaria de injetar um daoGenerico, passando em tempo de execução a classe para o DAO.

<bean id="genericDao" class="package br.al.gov.seagri.persistencia.hibernate.SpringFactoryDAO"
		scope="prototype" factory-method="createDAO">
</bean>

O metodo createDAO receberia a classe, para instanciar o DAO generico, por exemplo:
GenericDaoHibernateImpl<Propriedade,Integer>

public class SpringFactoryDAO {
	public static <T>  GenericDao<T, Integer> createDAO(Class<T> c){
		return new GenericDaoHibernateImpl<T, Integer>(c);
	}
}

Porém não sei como passar valores em execução para o factoryBean, o metodo getBean(String nameBean, Object[] args), mas como seria a conf no xml. Até agora soh vi construtores q usam referencias de outros beans, ou qq literal, mas não valores passados como parametro.

Se nao estiver claro, eu posterei codigo.

[quote=thiagoAraujo_al]Pessoal,

Tenho uma interface genérica e uma implementação generica com hibernate para meus DAOs. Não gostaria de escrever para da um dos meus DAOs a classe extendida dessa implementação do hibernate generica. Uma solução seria mapear inumeros no meu applicationContext.xml

<bean id="culturaDao" class="br.al.gov.seagri.persistencia.dao.GenericDaoHibernateImpl">
		<constructor-arg>
			<value>br.al.gov.seagri.dominio.Cultura</value>
		</constructor-arg>
		<property name="sessionFactory" ref="sessionFactory"/>
	</bean>
	
	<bean id="propriedadeDao" class="br.al.gov.seagri.persistencia.dao.GenericDaoHibernateImpl">
		<constructor-arg>
			<value>br.al.gov.seagri.dominio.Propriedade</value>
		</constructor-arg>
		<property name="sessionFactory" ref="sessionFactory"/>
	</bean>
.........

São muitos DAOs, gostaria de injetar um daoGenerico, passando em tempo de execução a classe para o DAO.

<bean id="genericDao" class="package br.al.gov.seagri.persistencia.hibernate.SpringFactoryDAO"
		scope="prototype" factory-method="createDAO">
</bean>

O metodo createDAO receberia a classe, para instanciar o DAO generico, por exemplo:
GenericDaoHibernateImpl<Propriedade,Integer>

public class SpringFactoryDAO {
	public static <T>  GenericDao<T, Integer> createDAO(Class<T> c){
		return new GenericDaoHibernateImpl<T, Integer>(c);
	}
}

Porém não sei como passar valores em execução para o factoryBean, o metodo getBean(String nameBean, Object[] args), mas como seria a conf no xml. Até agora soh vi construtores q usam referencias de outros beans, ou qq literal, mas não valores passados como parametro.

Se nao estiver claro, eu posterei codigo.[/quote]

Oi thiago,

Olhando neste artigo eu achei uma solução bem legal de implementação.

A grande sacada é na hora de você configurar o spring, você coloca algo assim

<beans> <bean id="gerenteDao" class="acme.GenericDAOHibernateImpl"> <constructor-arg> <value>acme.vo.Gerente</value> </constructor-arg> </bean> </beans>

No GenericDAOHibernate

[code]private Class type;

public GenericDAOHibernateImpl(Class type) {
this.type = type;
}

public PK create(T o) {
PK pk=null;
try {
Session session = HibernateUtil.currentSession();
Transaction tx = session.beginTransaction();
pk = (PK) session.save(o);
tx.commit();
} catch (HibernateException e) {
e.printStackTrace();
}
return pk;
}

// outros métodos aqui[/code]

E para usar

[code]FileSystemResourceLoader fsl = new FileSystemResourceLoader();
Resource rs = fsl.getResource(“src/resources/beans-spring.xml”);
XmlBeanFactory factory = new XmlBeanFactory(rs);
GenericDAO dao = (GenericDAO) factory.getBean(“gerenteDao”);

Gerente gerente = new Gerente();
gerente.setCelular(“4455-1011”);
gerente.setEmail("jose.carlos@mail.com");
gerente.setNome(“José Carlos”);
gerente.setTelefone(“8444-8999”);

dao.create(gerente);[/code]

Para criar um novo DAO genérico basta criar uma nova entrada no beans-spring.xml

Abs

André, vlw mas acho que vc nao entendeu

Eu queria NÃO precisa mapear todos os beans DAOS no applicationContext. Gostaria de mapear uma fabrica que recebesse como parametro da classe que quero usar, pois para a maioria dos meus POJOS o generic HibernateDaoImpl da conta,de buscas por exemplo, CRUD e tal. Mas como preciso de uma instância “tipada” preciso passar como parâmetro a minha classe e no factory-method do bean factory me retornar a implementação que desejo.

Para isso, “TALVEZ ,nao sei como”, o Spring tem um método que recebe um segundo parametro no getBean, um Object[].
Aí em linha de código:

clienteDAO =(ClienteDAO<Cliente, Integer>) factoryBean.getBean("factorySpringDAO", Cliente.class)

O Spring executaria o factory-metod passando como parâmetro a classe, tipo:

return new GenericDaoHibernateImpl<T, Integer>(c);

Senão conseguir vou mapear os beans mesmo,
MInha dúvida eh como mapear o .xml para receber o tipo da classe qnd chamar o getBean(“name”, class)

Oi,

Entendi o que você quer, bom não sei se tem esta propriedade… bom eu gostei dessa forma que coloquei acima, nem são tantas linhas assim no XML… 8)

Abs

Essa solução entendo como a melhor, e é a que atualmente utilizo. Mas tive essa sacada do injetar a fábrica que só na hora da chamada me desse o DAO requerido. Assim teria apenas um bean no XML. Com a solução atual se eu tiver 20 DAO serão 20 beans. :frowning:

Mas fica aí essa solução como uma proposta.

vlw André

[quote=thiagoAraujo_al]Essa solução entendo como a melhor, e é a que atualmente utilizo. Mas tive essa sacada do injetar a fábrica que só na hora da chamada me desse o DAO requerido. Assim teria apenas um bean no XML. Com a solução atual se eu tiver 20 DAO serão 20 beans. :frowning:

Mas fica aí essa solução como uma proposta.

vlw André

[/quote]

Opa, Tiago, você conseguiu resolver isso?
Estou passando pela mesma situação.

rafaelunp,

Usei como está descrito acima, usando genirics e uma fábrica de DAOs, que passa os os tipos como parametros para FactoryBean, p/ recuperar os beans mapeados no applicationContext.

Atualmente uso o JBoss Seam e estou muito satisfeito com suas features e com a produtividade.