【问题标题】:hibernate Custom Multiple Fields Selection休眠自定义多个字段选择
【发布时间】:2017-02-05 22:09:14
【问题描述】:

我们有几种型号,如下所示。

@Entity
@Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Person {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    public int id;

    @Column(nullable = false, columnDefinition = "text")
    public String name;

    @Column(nullable = false, unique = true)
    public long ssid;

    @Column(nullable = false)
    public int age;

    @Column(nullable = false)
    public long registration;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "person")
    @Cascade(CascadeType.ALL)
    public List<Car> cars;


}

车型

@Entity
@Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Car {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    public int id;

    @Column(nullable = false, columnDefinition = "text")
    private String name;

    @Column(nullable = false,  unique = true)
    public String plateNumber;

    @ManyToOne(fetch = FetchType.LAZY)
    public Person person;

    @ManyToOne(fetch = FetchType.LAZY)
    public Fabric fabric;

}

面料型号

@Entity
@Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Fabric {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    public int id;


    @Column(nullable = false, columnDefinition = "text")
    public String name;


    @OneToMany(fetch = FetchType.LAZY, mappedBy = "fabric")
    @Cascade(CascadeType.ALL)
    public List<Car> cars;
}

问题是,我们在不同的模块上只使用模型的 一些 属性。当我们调用简单类型的属性时是可以的,但是当查询这样的东西时;

session.createQuery("select name, cars from Person order by registration desc ");

我们得到错误。有人可以帮忙吗?

   org.springframework.web.util.NestedServletException: Request processing failed; nested exception is javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: could not extract ResultSet
        org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982)
        org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
        org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
        org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
        org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
        org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
        org.apache.logging.log4j.web.Log4jServletFilter.doFilter(Log4jServletFilter.java:71)

org.hibernate.exception.SQLGrammarException: could not extract ResultSet
    org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:63)
    org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
    org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111)
    org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:97)
    org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:79)
    org.hibernate.loader.Loader.getResultSet(Loader.java:2123)
    org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1911)
    org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1887)
    org.hibernate.loader.Loader.doQuery(Loader.java:932)
    org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:349)
    org.hibernate.loader.Loader.doList(Loader.java:2615)
    org.hibernate.loader.Loader.doList(Loader.java:2598)
    org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2430)
    org.hibernate.loader.Loader.list(Loader.java:2425)
    org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:502)
    org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:370)
    org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:216)
    org.hibernate.internal.SessionImpl.list(SessionImpl.java:1481)
    org.hibernate.query.internal.AbstractProducedQuery.doList(AbstractProducedQuery.java:1441)
    org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1410)
    org.hibernate.Query.getResultList(Query.java:427)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    java.lang.reflect.Method.invoke(Method.java:498)
    org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333)
    org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
    org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)
    org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
    com.sun.proxy.$Proxy88.getAllPostOverview(Unknown Source)
    jarvis.api.story.PostController.getAllPostOverviews(PostController.java:51)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    java.lang.reflect.Method.invoke(Method.java:498)
    org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:220)
    org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:134)
    org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:116)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
    org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    org.apache.logging.log4j.web.Log4jServletFilter.doFilter(Log4jServletFilter.java:71)

【问题讨论】:

  • 您能否提供完整的堆栈跟踪以便我们查看根本原因?
  • 同时添加汽车实体代码
  • @MaciejKowalski 我上传了模型
  • 错误的完整轨迹怎么样,@raigeki?
  • @Naros 我已经上传了堆栈跟踪

标签: java spring hibernate hql


【解决方案1】:

不要将cars 指定为查询中的字段。

尝试添加 LEFT JOIN FETCH 子句,关联集合的 Person 实体将在单个查询中加载:

SELECT p.name FROM Person p LEFT JOIN FETCH p.cars ORDER BY p.registration DESC

【讨论】:

  • 这并不能解决 OP 只想获取特定列作为结果集有效负载的一部分的问题。
  • 而您的编辑结果只返回名称,而不是名称〜和〜他们想要的汽车集合。
  • 不,我已经试过了。简而言之,LEFT JOIN FETCH 避免了在编译时指定的fetch = FetchType.LAZY 并强制加载汽车。
【解决方案2】:

JPA 不支持按照您的要求进行操作,至少不支持您尝试采用的路径。但是如果你从Car的角度来看待问题,你就可以。

SELECT c, c.person.name FROM Car c ORDER BY c.person.registration DESC

如果您想将此结果集自动填充到值对象中,您可以使用 SELECT NEW 语法或使用 JPA CriteriaBuilder#construct 方法。

SELECT NEW MyValueObject( c, c.person.name )
FROM Car c 
ORDER BY c.person.registration DESC

然后,您可以将 List&lt;MyValueObject&gt; 与 Java Stream API 结合使用,并根据需要在内存中对结果进行分组。

只要明白你得到的结果集包含:

  • Car 实例
  • 包含Person 名称值的String 实例。

更新

要构建关联Car 的映射,我可能会添加将c.person.id 作为另一个构造函数参数传递给MyValueObject,以防遇到两个同名的人的情况。

List<MyValueObject> queryResults = query.getResultList();
List<List<MyValueObject>> groupedResults = queryResults
  .stream()
  .collect( Collectors.groupingBy( MyValueObject::getPersonId ) )
  .values();

groupedResults 中的每个条目都是与给定 Person 相关联的 Car 实例列表,这些实例封装为 MyValueObject 实例。

【讨论】:

  • 我需要列出人名和他/她的汽车作为收藏
【解决方案3】:

你可以试试这个……

session.createQuery("Select ps.name from Person as ps JOIN FETCH ps.cars ORDER BY ps.registration DESC");

【讨论】:

    猜你喜欢
    • 2012-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-27
    • 1970-01-01
    • 2011-03-06
    • 2021-12-18
    相关资源
    最近更新 更多