简体   繁体   English

从泛型类派生的类没有获得正确的类型

[英]Class derived from generic class don't get the correct type

In my spring project, I have this template for my Dao classes: 在我的春季项目中,我的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;
    }

}

Each one of my Dao classes have this structure: 我的每个Dao类都具有以下结构:

@Repository
public class UsuarioHome extends Dao<Usuario> {

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

}

Which means that when I call the methods findById, findByField, findAll, I should receive a object from types Usuario, Usuario and List. 这意味着当我调用方法findById,findByField,findAll时,我应该从Usuario,Usuario和List类型接收对象。

The two fist classesa re returning the right value, but the Last one don't. 这两个拳头类的返回正确值,但最后一个不返回。 When I run this method (from my service class): 当我运行此方法时(从我的服务类中):

@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;
}

I am receiving "object" as response, when I should see "usuario". 我应该看到“ usuario”时收到“对象”作为响应。 Anyone can tell what I doing wrong here? 有人可以告诉我我在做什么错吗?

I strongly suspect that this is the problem: 我强烈怀疑这是问题所在:

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

You're effectively casting Usuario.class to Usuario . 您实际上是将Usuario.class强制Usuario.classUsuario That's not right. 那是不对的。 The class and an instance of the class are different things. 类和类的实例是不同的东西。 The class is not an entity - it's the type of the entity. 该类不是实体-它是实体的类型。

It's not clear what you're trying to do with the entity field (you're calling toString() on it - what do you expect the result to be?) but I suspect you should actually have an entityClass field instead, which is a Class<E> or a Class<? extends E> 尚不清楚您要对entity字段进行什么操作(正在调用toString() -您期望结果是什么?),但我怀疑您实际上应该有一个entityClass字段,这是一个Class<E>Class<? extends E> Class<? extends E> . Class<? extends E> Fundamentally, you need to distinguish between the two concepts though. 从根本上讲,您需要区分这两个概念。

Your findAll() method is wrong. 您的findAll()方法错误。 It uses a SQL query which selects all the columns of the table named usuario, which returns a List<Object[] >, instead of using an HQL query returning all the instances of the generic entity. 它使用一个SQL查询来选择名为usuario的表的所有列,该查询返回一个List<Object[] >,而不是使用一个HQL查询返回该泛型实体的所有实例。 The code should be 该代码应为

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

This is correct provided the entity field contains the entity class (ie Usuario.class in this case). 如果实体字段包含实体 (在这种情况下,即Usuario.class ,这是正确的。 See Jon Skeet's answer for an explanation on this. 有关此说明,请参阅乔恩·斯基特(Jon Skeet)的答案。

The problem is in your generic DAO findAll method; 问题出在您的通用DAO findAll方法中。 you are using query string select * from usuario 您正在使用查询字符串select * from usuario

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

How try with like this; 怎么这样尝试?

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

Here are also suggestions for your template DAO class; 这也是您的模板DAO类的建议;

  1. I prefer to this variable declaration 我更喜欢这个变量声明

     private Class<E> entity; 
  2. And in constructor with class argument 并在带有class参数的构造函数中

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM