简体   繁体   中英

Problems when using inheritance with Hibernate

I am working on a little exercise and I am facing some problems when calling a select query.

Basically I've created an Abstract class in the following way:

//AbstractStage
entity --class ~.AbstractStage --mappedSuperclass  --abstract 
field date --fieldName datetime --type java.util.Date --notNull
field boolean --fieldName iscomplete --type java.util.boolean

and two subclasses as following:

//
// HappyStage
//
entity --table happy_stage --class ~.HappyStage --extends  ~.AbstractStage --testAutomatically --identifierField id --identifierColumn id_happy_stage
field boolean --fieldName isSad --type java.util.boolean
field date --fieldName dateOfDeath --type java.util.Date --notNull
finder add findHappyStagesByIscomplete

and

   //
   // HStage
   //
   entity --table h_stage --class ~.HStage --extends ~.AbstractStage  --testAutomatically --identifierField id --identifierColumn id_h_stage
    field boolean --fieldName isHappy --type java.util.boolean
    field date --fieldName dateOfBirth --type java.util.Date --notNull

My environment is:

Java
SpringTool
Roo
Hibernate

I've also run a persistence roo command:

persistence setup --provider HIBERNATE --database MYSQL

Then I've wrote the controller class as following:

package test;

import java.util.Date;

import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;

import org.springframework.roo.addon.web.mvc.controller.RooWebScaffold;
import test.HappyStage;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.stereotype.Controller;

@RooWebScaffold(path = "happystages", formBackingObject = HappyStage.class)
@RequestMapping("/happystages")
@Controller
public class HappyStageController {

 @RequestMapping(value="/happy", method=RequestMethod.GET)
 public String get() throws Exception
 {

 // TypedQuery<AbstractStage> queryResults = HappyStage.findAbstractStagesByIscomplete(true);
  Date dd = new Date();
  TypedQuery<AbstractStage> queryResults = HappyStage.findAbstractStagesByDateGreaterThan(dd);

  System.err.println("N.of abstractstages found: " + queryResults.getResultList().size());
  return "redirect:/InheritanceTest";  
 }  

}

HappyStage has the method findAbstractStagesByDateGreaterThan. The idea was to call this method from the subclass and gett all the abstract stages with date greater than.

q = em.createQuery("FROM test.AbstractStage AS abstractstage WHERE abstractstage.datetime > :datetime", AbstractStage.class);

Here is the HappyStage class code:

package test;

import test.AbstractStage;
import org.springframework.roo.addon.javabean.RooJavaBean;
import org.springframework.roo.addon.tostring.RooToString;
import org.springframework.roo.addon.entity.RooEntity;
import java.util.Date;
import javax.validation.constraints.NotNull;
import javax.persistence.EntityManager;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.TypedQuery;
import org.springframework.format.annotation.DateTimeFormat;

@RooJavaBean
@RooToString
@RooEntity(identifierField = "id", identifierColumn = "id_happy_stage", table = "happy_stage", finders = { "findHappyStagesByIscomplete", "findHappyStagesByDatetimeGreaterThan" })
public class HappyStage extends AbstractStage {

    private Boolean isSad;

    @NotNull
    @Temporal(TemporalType.TIMESTAMP)
    @DateTimeFormat(style = "S-")
    private Date dateOfDeath;

    public static TypedQuery<AbstractStage> findAbstractStagesByIscomplete(Boolean iscomplete) throws Exception {
        if (iscomplete == null) throw new IllegalArgumentException("The iscomplete argument is required");
        EntityManager em = HappyStage.entityManager();
        TypedQuery<AbstractStage> q = null;
        try {
            q = em.createQuery("FROM test.AbstractStage AS abstractstage WHERE abstractstage.iscomplete = :iscomplete", AbstractStage.class);
          q.setParameter("iscomplete", iscomplete);

        } catch (Exception exp) {
          System.err.println("Ex message:\n" + exp + "\nStack trace \n" );

          int stLenght =  exp.getStackTrace().length;
          StackTraceElement [] ste = exp.getStackTrace();
         for(int i=0; i<stLenght; i++){
           System.err.println("message [" + i + "]" + ste[i].toString());          
         }
            throw(exp);

        }
        return q;
    }


    public static TypedQuery<AbstractStage> findAbstractStagesByDateGreaterThan(Date datetime) throws Exception {

        EntityManager em = HappyStage.entityManager();
        TypedQuery<AbstractStage> q = null;
        try { 
            q = em.createQuery("FROM test.AbstractStage AS abstractstage WHERE abstractstage.datetime > :datetime", AbstractStage.class);
         q.setParameter("datetime", datetime);

        } catch (Exception exp) {
            System.err.println("Ex message:\n" + exp);
            throw(exp);
        }
        return q;
    }    

}

The problem is that when I run the code as on server and go to the * /happystages/happy I get a nullPointer exception with the following stack trace:. *

org.hibernate.ejb.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:281)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:365)
$Proxy48.createQuery(Unknown Source)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:240)
$Proxy49.createQuery(Unknown Source)
test.HappyStage.findAbstractStagesByDateGreaterThan_aroundBody2(HappyStage.java:55)
test.HappyStage.findAbstractStagesByDateGreaterThan(HappyStage.java:1)
test.HappyStageController.get(HappyStageController.java:25)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:426)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:414)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549)
javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:113)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
com.springsource.insight.collection.tcserver.request.HttpRequestOperationCollectionValve.traceNextValve(HttpRequestOperationCollectionValve.java:90)
com.springsource.insight.collection.tcserver.request.HttpRequestOperationCollectionValve.invoke(HttpRequestOperationCollectionValve.java:76)
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:857)
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:409)
java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
java.lang.Thread.run(Thread.java:680)

Running a JUnit test we have identified that probably the error is in the exception is linked to how Hibernate handles the SQL query. Adding some breakpoints we found that this might be the code involved:

/**
 * Abstract implementation of the Query interface.
 *
 * @author Gavin King
 * @author Max Andersen
 */

public abstract class AbstractQueryImpl implements Query {

....
 public Type[] getReturnTypes() throws HibernateException {
  return session.getFactory().getReturnTypes( queryString );
 }

...
}

We are now breaking down the code a bit more but * I was wondering if any of you has already experienced a similar problem. Is there anything I am missing? Is alright to have an abstract class as parent class or would be necessary to have it as a "concrete" class? * It just seems odd to me that you cannot have an abstract class and extend it and then use it to query all the subclasses with a query based onthe inherited value.

Please ask me for clarifications as my question might not have been explained properly.

Best Regards

PS: I've tried as well without the --Abstract keyword in the AbstractClass. It still doesn't work and gives me this expetion when going to happystages/happy and triggering the get method (which calls: TypedQuery queryResults = HappyStage.findAbstractStagesByDateGreaterThan(dd) ; )"

org.hibernate.ejb.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:281)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:365)
$Proxy48.createQuery(Unknown Source)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:240)
$Proxy49.createQuery(Unknown Source)
test.HappyStage.findAbstractStagesByDateGreaterThan_aroundBody2(HappyStage.java:55)
test.HappyStage.findAbstractStagesByDateGreaterThan(HappyStage.java:1)
test.HappyStageController.get(HappyStageController.java:25)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
java.lang.reflect.Method.invoke(Method.java:597)
org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:426)
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:414)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549)
javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:113)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
com.springsource.insight.collection.tcserver.request.HttpRequestOperationCollectionValve.traceNextValve(HttpRequestOperationCollectionValve.java:90)
com.springsource.insight.collection.tcserver.request.HttpRequestOperationCollectionValve.invoke(HttpRequestOperationCollectionValve.java:76)
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:857)
org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:409)
java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
java.lang.Thread.run(Thread.java:680)

It seems that it doesn't have to do with MySQl and Abstract as I've also translated the dialect SQL query used by hibernate into a real SQL query and I've run it on the MySQL shell directly

I've actually tried now by removing the mapped superclass tag and it seems to be working. I found this answer and seems to solve the problem:

Hibernate ManyToMany and superclass mapping problem

alghough there is a little bug with roo 1.0.1 and someone has been posting about that on the spring community forum:

http://forum.springsource.org/showthread.php?p=333182#post333182

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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