Implementacao de DAO Generico e Heranca

Pessoal,

Estou aqui no site pesquisando sobre DAO Generico e me deparei com uma dúvida.

Primeiramente, tenho as classes:

class Pessoa {
	//atributos
}

class PessoaFisica extends Pessoa {
	//atributos
}

class PessoaJuridica extends Pessoa {
	//atributos
}

E tenho meu GenericDAO feito conforme já discutido varias vezes aqui:

public interface GenericDAO<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);
}

ai tenho a problematica da herança:

class PessoaDAO extends GenericDAO<Pessoa, Integer>() {}

class PessoaFisicaDAO extends PessoaDAO() {
	//metodos especificos
}

class PessoaJuridicaDAO extends PessoaDAO() {
	//metodos especificos
}

Por fim, para usar, seria algo como:

PessoaDAO pDAO = DAOFactory.getInstance().getDAO(PessoaDAO.class);
Pessoa p = new Pessoa();
pDAO.save(p);

Até aqui tudo bem, pois o generics me retornaria uma pessoa e os metodos do GenericDAO estariam aptos a receber Pessoa.

Contudo, se eu precisasse atualizar PessoaFisica ?

PessoaFisicaDAO pfDAO = DAOFactory.getInstance().getDAO(PessoaFisicaDAO.class);
PessoaFisica pf = new PessoaFisica();
pfDAO.save(pf);

o Metodo save estaria esperando uma Pessoa e não PessoaFisica.

Alguém sabe como resolver isso?

Grato

Eu jogaria um generics na classe Pessoa também.

[code]class PessoaDAO

extends GenericDAO<Pessoa, Integer>() {}

class PessoaFisicaDAO extends PessoaDAO() {
//metodos especificos
} [/code]

class PessoaDAO extends GenericDAO<T extends Pessoa, Integer>

Ou seja, PessoaDAO é um GenericDAO para qualquer classe que estenda Pessoa.

[quote=rmendes08] class PessoaDAO extends GenericDAO<T extends Pessoa, Integer>

Ou seja, PessoaDAO é um GenericDAO para qualquer classe que estenda Pessoa.[/quote]

Certo, neste caso, a implementacao seria?

caso 1:

PessoaDAO<Pessoa> pDAO = DAOFactory.getInstance().getDAO(PessoaDAO.class);
Pessoa p = new Pessoa();
pDAO.save(p);

caso 2:

PessoaFisicaDAO<PessoaFisica> pfDAO = DAOFactory.getInstance().getDAO(PessoaFisicaDAO.class);
PessoaFisica pf = new PessoaFisica();
pfDAO.save(pf);

Certo?

No caso, se for por ioc, da pra fazer com esses generics?

grato

[code]public class Dao {

private Class<T> classeEntidade;
private EntityManager entityManagerFilho;
private EntityManagerFactory entityManagerFactoryFilho;

/**
 * 
 * @return EntityManager
 */
protected EntityManager getEntityManager() {
	if (entityManagerFilho == null) {
		try {
			@SuppressWarnings("rawtypes")
			Class clazz = this.getClass();

			Field field = clazz.getDeclaredField("entityManagerFactory");
			field.setAccessible(true);
			entityManagerFactoryFilho = (EntityManagerFactory) field.get(this);

			if (entityManagerFactoryFilho == null) {
				Field fieldEntity = clazz.getDeclaredField("entityManager");
				fieldEntity.setAccessible(true);
				entityManagerFilho = (EntityManager) fieldEntity.get(this);
			} else {
				entityManagerFilho = entityManagerFactoryFilho.createEntityManager();
			}
			return entityManagerFilho;
		} catch (Exception e) {
			throw new ExcecaoProcessamentoSistema("Não foi possível encontrar a propridade entitymanager/entityManagerFactory para o dao " + this.getClass().getCanonicalName());
		}
	} else {
		return entityManagerFilho;
	}
}

/**
 * 
 * @return
 */
@SuppressWarnings("unchecked")
protected Class<T> getClasseEntidade() {
	if (classeEntidade == null) {
		@SuppressWarnings("rawtypes")
		Class classeDaoCorrente = this.getClass();
		if (classeDaoCorrente == null) {
			throw new ExcecaoProcessamentoSistema("Não foi possível identificar a classe da entidade no dao.");
		}
		ParameterizedType genericsClasseDaoCorrente = (ParameterizedType) classeDaoCorrente.getGenericSuperclass();
		if (genericsClasseDaoCorrente == null) {
			throw new ExcecaoProcessamentoSistema("Não foi possível identificar o generics da classe da entidade no dao.");
		}

		Type[] tiposDoGeneric = genericsClasseDaoCorrente.getActualTypeArguments();
		if (tiposDoGeneric == null) {
			throw new ExcecaoProcessamentoSistema("Não foi possível identificar o generics da classe da entidade no dao.");
		}

		if (tiposDoGeneric.length < 1) {
			throw new ExcecaoProcessamentoSistema("O generics da classe da entidade no dao  nao foi inicializado.");
		}

		classeEntidade = (Class<T>) tiposDoGeneric[0];
	}
	return classeEntidade;
}

/**
 * 
 * @param id
 * @return
 */
public T buscar(Serializable id) {
	return getEntityManager().find(classeEntidade, id);
}

/**
 * 
 * @param entidade
 */
public void registrar(T entidade) {
	getEntityManager().merge(entidade);
}

/**
 * 
 * @param entidade
 */
public void armazenar(T entidade) {
	getEntityManager().persist(entidade);
}

/**
 * 
 * @param entidade
 */
public void remover(T entidade) {
	getEntityManager().remove(entidade);
}

/**
 * 
 * @param id
 */
public void remover(Serializable id) {
	Entidade entidade = buscar(id);
	getEntityManager().remove(entidade);
}

public void flush() {
	getEntityManager().flush();
}

@SuppressWarnings("unchecked")
public List<T> buscarTodos() {
	NamedQuery namedQuery = getQueryBuscarTodos(classeEntidade);
	Query query = null;
	if (namedQuery == null) {
		String newQuery = "FROM ".concat(classeEntidade.getSimpleName());
		query = getEntityManager().createQuery(newQuery);
	} else {
		query = getEntityManager().createNamedQuery(namedQuery.name());
	}

	return query.getResultList();
}

/**
 * 
 * @param classe
 * @return
 */
private NamedQuery getQueryBuscarTodos(Class<?> clazz) {
	NamedQueries namedQueries = (NamedQueries) clazz.getAnnotation(NamedQueries.class);
	if (namedQueries != null) {
		for (NamedQuery namedQuery : namedQueries.value()) {
			if (namedQuery.name().equalsIgnoreCase(clazz.getSimpleName() + ".buscarTodos")) {
				return namedQuery;
			}
		}
	}
	return null;
}

/**
 * 
 * @param nomeQuery
 * @param parametros
 * @return
 */
@SuppressWarnings("unchecked")
public List<T> buscarQueryPorNome(String nomeQuery, Object... parametros) {
	Query query = getEntityManager().createNamedQuery(nomeQuery);
	if ((parametros != null) && (parametros.length > 0)) {
		for (int i = 0; i < parametros.length; ++i) {
			query.setParameter(i + 1, parametros[i]);
		}
	}
	return query.getResultList();
}

/**
 * 
 * @param nomeQuery
 * @param parametros
 * @return
 */
@SuppressWarnings("unchecked")
public List<T> buscarQueryPorNome(String nomeQuery, Map<String, Object> parametros) {
	Query query = getEntityManager().createNamedQuery(nomeQuery);

	for (String key : parametros.keySet()) {
		query.setParameter(key, parametros.get(key));
	}
	return query.getResultList();

}

/**
 * 
 * @param nomeQuery
 * @param parametros
 * @return
 */
public Integer executarAteracao(String nomeQuery, Object... parametros) {
	Query query = getEntityManager().createNamedQuery(nomeQuery);
	if ((parametros != null) && (parametros.length > 0)) {
		for (int i = 0; i < parametros.length; ++i) {
			query.setParameter(i, parametros[i]);
		}
	}
	return Integer.valueOf(query.executeUpdate());
}

}

[/code]

[code]
@Stateless
public class PessoaDAO extends Dao {
@PersistenceContext(unitName = “pu1”)
private EntityManager entityManager;

}[/code]

@Stateless
public class PessoaFisicaDAO extends Dao<PessoaFisica> {
	@SuppressWarnings("unused")
	@PersistenceContext(unitName = "pu1")
	private EntityManager entityManager;

}
@Stateless
public class PessoaJuridicaDAO extends Dao<PessoaJuridica> {
	@PersistenceContext(unitName = "pu1")
	private EntityManager entityManager;

}