Reputation: 9095
In my spring project, I have this template for my Dao classes:
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:
@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.
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". Anyone can tell what I doing wrong here?
Upvotes: 0
Views: 811
Reputation: 3475
The problem is in your generic DAO
findAll method; you are using query string 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;
I prefer to this variable declaration
private Class<E> entity;
And in constructor with class
argument
public Dao(Class<E> clazz) {
this.entity = clazz;
}
Upvotes: 1
Reputation: 692181
Your findAll()
method is wrong. 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. 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 (i.e. Usuario.class
in this case). See Jon Skeet's answer for an explanation on this.
Upvotes: 2
Reputation: 1503469
I strongly suspect that this is the problem:
public Dao(Class<?> classe) {
this.entity = (E) classe;
}
You're effectively casting Usuario.class
to Usuario
. 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>
. Fundamentally, you need to distinguish between the two concepts though.
Upvotes: 2