从泛型类派生的类不能获得正确的类型

时间:2014-05-20 11:51:59

标签: java hibernate generics dao

在我的春季项目中,我为我的Dao课程设计了这个模板:

public class Dao<E> {

    private final E entity;

    @Autowired
    SessionFactory sessionFactory;

    protected Session getCurrentSession(){
        return sessionFactory.getCurrentSession();
    }

    public Dao(E entity) {  
        this.entity = entity;
    }

    public Dao(Class<?> classe) {
        this.entity = (E) classe;
    }

    public E getEntity() {
        return this.entity;
    }

    @Transactional
    public boolean persist(E transientInstance) {
        sessionFactory.getCurrentSession().persist(transientInstance);
        return true;
    }

    @Transactional
    public boolean remove(E transientInstance) {
        sessionFactory.getCurrentSession().delete(transientInstance);
        return true;
    }

    @Transactional
    public boolean merge(E detachedInstance) {
        sessionFactory.getCurrentSession().merge(detachedInstance);
        return true;
    }

    @Transactional
    public E findById(int id) {
        E instance = (E) sessionFactory.getCurrentSession().get(entity.getClass(), id);
        return instance;
    }

    @Transactional
    public E findByField(String field, String value) {
        String expressao = entity.toString();
        String nome_classe = new String();
        StringTokenizer st = new StringTokenizer(expressao);
        while (st.hasMoreTokens()) {
            nome_classe = st.nextToken();
        }
        String query = "from "+nome_classe+" where "+field+" = :data";

        Query q = sessionFactory.getCurrentSession().createQuery(query);
        q.setParameter("data", value);
        E instance = (E) q.uniqueResult();
        return instance;
    }

    @Transactional
    public List<E> findAll() {
        List<E> instance = (List<E>) sessionFactory.getCurrentSession().createSQLQuery("select * from usuario").list();
        return instance;
    }

}

我的每个Dao类都有这样的结构:

@Repository
public class UsuarioHome extends Dao<Usuario> {

    public UsuarioHome() {
        super(Usuario.class);
    }

}

这意味着当我调用方法findById,findByField,findAll时,我应该从Usuario,Usuario和List类型中接收一个对象。

两个拳头类别重新返回正确的值,但最后一个没有。当我运行此方法(来自我的服务类)时:

@Transactional
public List<Usuario> listagem_usuarios() {
    List<Usuario> lista = usuario.findAll();
    System.out.println("listagem_usuario find "+lista.size()+" users");
    System.out.println(lista.getClass().getName());
    for(int i=0; i<lista.size(); i++) {
        System.out.println("i = "+i+" {");
        if(lista.get(i) instanceof Usuario)
            System.out.println("usuario");
        else if(lista.get(i) instanceof Object)
            System.out.println("object");
        else
            System.out.println("outro");
        System.out.println("}");
    }
    return lista;
}

当我看到“usuario”时,我收到“对象”作为回应。谁能告诉我这里做错了什么?

3 个答案:

答案 0 :(得分:2)

我强烈怀疑这是问题所在:

public Dao(Class<?> classe) {
    this.entity = (E) classe;
}

您有效地将Usuario.class投射到Usuario。那不对。类和类的实例是不同的东西。该类不是实体 - 它是实体的类型。

您不清楚自己要对entity字段做什么(您在其上调用toString() - 您希望结果是什么? ?)但我怀疑你实际上应该有entityClass字段,而是Class<E>Class<? extends E>。从根本上说,你需要区分这两个概念。

答案 1 :(得分:2)

您的findAll()方法错误。它使用SQL查询选择名为usuario的的所有列,该列返回List<Object[]&gt;而不是使用返回通用实体的所有实例的HQL查询。代码应该是

String hql = "select u from " + entity.getName() + " u";
return (List<E>) sessionFactory.getCurrentSession().createQuery(hql).list();

这是正确的,前提是实体字段包含实体(在本例中为Usuario.class)。有关此问题的解释,请参阅Jon Skeet的答案。

答案 2 :(得分:1)

问题在于您的通用DAO findAll方法;您正在使用查询字符串select * from usuario

@Transactional
public List<E> findAll() {
        List<E> instance = (List<E>) sessionFactory.getCurrentSession().createSQLQuery("select * from usuario").list();
        return instance;
}

如何尝试这样;

@Transactional
public List<E> findAll() {
return (List<E>) sessionFactory.getCurrentSession().createCriteria(entity)
        .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY).list();
}

以下是您的模板DAO类;

的建议
  1. 我更喜欢这个变量声明

    private Class<E> entity;
    
  2. class参数

    的构造函数中
    public Dao(Class<E> clazz) {
        this.entity = clazz;
    }