1

I am implementing a Restful Web Service using Jersey. I have a package using hibernate to map the data to DB. I am new to hibernate using DAO :

I have a method in GenericDao class :

public abstract class GenericDAO<T> extends DAOFactory {

    private final Class classe;

        public GenericDAO(Class classe) {
            this.classe = classe;
        }

           public List<T> findByCriteria(List<Criterion> list) throws Exception {
                Criteria criteria = getSession().createCriteria(classe);
                for (int i = 0; i < list.size(); i++) 
                   criteria.add(list.get(i));
                return criteria.list();
            }
        }

Then I have my DAO classes like :

public class TaskDAO extends GenericDAO<Task> {

    public TaskDAO() {
        super(Task.class);
    }
}

Then I use this method in a Service class and it works completely fine like this:

 public Response get(long projectId, String username) {
    List<Criterion> list = new ArrayList<Criterion>();
    Criterion c = Restrictions.eq("project.id", projectId);
    list.add(c);
    List<Deliverable> deliverables = deliverableDAO.findByCriteria(list);
    return deliverables
}

The problem is in this method in another Service class :

public Response get(String username) {
    List<Criterion> list = new ArrayList<Criterion>();
    Criterion c = Restrictions.eq("user.username", username);
    list.add(c);
    List<Task> tasks = taskDAO.findByCriteria(list);
    return tasks;
}

as you see "Restrictions.eq("project.id", projectId)" works fine for me but "Restrictions.eq("user.username", username)" has a promlem maybe with 'user.username',
Any help?

The error in the stack trace is like:

javax.ws.rs.WebApplicationException: org.hibernate.QueryException: could not resolve property: user.username of: se.softwerk.timelog.model.Task
    at se.softwerk.controller.services.TaskService.get(TaskService.java:29)
    at se.softwerk.timelog.controller.TaskManager.taskList(TaskManager.java:72)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at com.sun.jersey.spi.container.JavaMethodInvokerFactory$1.invoke(JavaMethodInvokerFactory.java:60)
    at com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$ResponseOutInvoker._dispatch(AbstractResourceMethodDispatchProvider.java:205)
    at com.sun.jersey.server.impl.model.method.dispatch.ResourceJavaMethodDispatcher.dispatch(ResourceJavaMethodDispatcher.java:75)
    at com.sun.jersey.server.impl.uri.rules.HttpMethodRule.accept(HttpMethodRule.java:288)
    at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:147)
    at com.sun.jersey.server.impl.uri.rules.ResourceClassRule.accept(ResourceClassRule.java:108)
    at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:147)
    at com.sun.jersey.server.impl.uri.rules.RootResourceClassesRule.accept(RootResourceClassesRule.java:84)
    at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1469)
    at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1400)
    at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1349)
    at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1339)
    at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:416)
    at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:537)
    at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:708)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:928)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:539)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:298)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Caused by: org.hibernate.QueryException: could not resolve property: user.username of: se.softwerk.timelog.model.Task
    at org.hibernate.persister.entity.AbstractPropertyMapping.propertyException(AbstractPropertyMapping.java:83)
    at org.hibernate.persister.entity.AbstractPropertyMapping.toColumns(AbstractPropertyMapping.java:98)
    at org.hibernate.persister.entity.BasicEntityPropertyMapping.toColumns(BasicEntityPropertyMapping.java:61)
    at org.hibernate.persister.entity.AbstractEntityPersister.toColumns(AbstractEntityPersister.java:1801)
    at org.hibernate.loader.criteria.CriteriaQueryTranslator.getColumns(CriteriaQueryTranslator.java:522)
    at org.hibernate.loader.criteria.CriteriaQueryTranslator.findColumns(CriteriaQueryTranslator.java:537)
    at org.hibernate.criterion.SimpleExpression.toSqlString(SimpleExpression.java:66)
    at org.hibernate.loader.criteria.CriteriaQueryTranslator.getWhereCondition(CriteriaQueryTranslator.java:419)
    at org.hibernate.loader.criteria.CriteriaJoinWalker.<init>(CriteriaJoinWalker.java:123)
    at org.hibernate.loader.criteria.CriteriaJoinWalker.<init>(CriteriaJoinWalker.java:92)
    at org.hibernate.loader.criteria.CriteriaLoader.<init>(CriteriaLoader.java:93)
    at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1464)
    at org.hibernate.internal.CriteriaImpl.list(CriteriaImpl.java:374)
    at se.softwerk.timelog.model.dao.GenericDAO.findByCriteria(GenericDAO.java:33)
    at se.softwerk.controller.services.TaskService.get(TaskService.java:24)
Ali
  • 9,800
  • 19
  • 72
  • 152

2 Answers2

0

You're using a variable 'classe'. What is it? Show the definition please.

You should be creating Criteria instance for particular class. So if you want to return a list of User object, you should refactor the code to look like this:

public List<T> findByCriteria(Class<?> askFor, List<Criterion> list) throws Exception {
        Criteria criteria = getSession().createCriteria(askFor);
        for (int i = 0; i < list.size(); i++) 
           criteria.add(list.get(i));
        return criteria.list();
    }

and later use it like this:

public Response get(String username) {
   List<Criterion> list = new ArrayList<Criterion>();
   Criterion c = Restrictions.eq("user.username", username);
   list.add(c);
   //this will create an alias
   List<Task> tasks = taskDAO.findByCriteria(Task.class, list);
   return tasks;
}

You should redesign your code, because what you're trying to achieve is to create an alias criteria to Task.user.username. Please read the corresponding section of the manual (15.4) http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/querycriteria.html

WeMakeSoftware
  • 9,039
  • 5
  • 34
  • 52
  • Thanks, Please check what is the definition of classe is. Obviously the same that you thought. what abuot project.id ? why that works fine? – Ali Jul 05 '12 at 19:20
  • your problem will be solved with createAlias("user","user"), but you don't have a place where to add it with current code. – WeMakeSoftware Jul 05 '12 at 19:22
0

You need to create a join to be able to access the fields of the user of the task:

criteria.createAlias("user", "theUser");
criteria.add(Restrictions.eq("theUser.username", username);

You don't need to do it for the ID of the project of the task, because the ID of the project is stored, as a foreign key, in the task table directly.

Design note: your DAO doesn't add much value. In particular, it doesn't isolate the service class from the persistence API (Hibernate, in this case). You might use the Hibernate session directly in your service class, and it wouldn't change much. Completely isolating the service class from the persistence API is useful for two main reasons:

  • it makes responsibilities clearer: the service class contains business logic, while the DAO contains persistence logic
  • it allows mocking the DAO in order to unit test the service.
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • I appreciate. I am using DAO because : "it's a matter of separating your code into manageable tiers of responsibility. If all of your hibernate code is mixed in other classes it's hard to make a single change that effects everything. Instead you should have 1 class (dao) that manages data access for a single object, or group of objects. It's following object oriented principles of encapsulation. So your dao is "wired" into your service tier (jersey) and you delegate the CRUD operations to the dao" – Ali Jul 05 '12 at 19:31
  • you can check this link for more information : http://stackoverflow.com/questions/11190934/rest-with-java-jax-rs-using-jersey – Ali Jul 05 '12 at 19:32
  • Do you think I do not need to use DAO ? – Ali Jul 05 '12 at 19:32
  • IF you are agree with using DAO (as you said the two important benefits of DAO) and you think that my implementation is poor, Can you please give me some help regarding how to implement my DAO in a proper way? (I appreciate if I can receive a link with some codes) – Ali Jul 05 '12 at 19:34
  • I think DAOs are a good thing. your DAO method, as it is, is just a thin generic layer over the generic Hibernate session. You must still create the restrictions, deal with persistent properties, etc. in the service class. And its genericity shows its limits, since you can't even create a join between entities. You shouldn't have a `findByCriteria(List restrictions)` method in your DAO: it's too generic. You should have a `findByUserName(String userName)`. Basically, you shouldn't use any class from the Hibernate API in the service. – JB Nizet Jul 05 '12 at 21:03