【问题标题】:Extract Year from date field using jpql and jpa使用 jpql 和 jpa 从日期字段中提取年份
【发布时间】:2016-03-21 14:10:43
【问题描述】:

我想从数据库中的一行中提取年份部分,以便将其与值进行比较。

这是我的功能

public List<Dossier> getAllDossierParAn() {
    Date date = new Date();
    Calendar calendar = new GregorianCalendar();
    calendar.setTime(date);
    int strI = calendar.get(Calendar.YEAR);
    TypedQuery<Dossier> query;
    query = em.createQuery("SELECT d FROM DOSSIER d WHERE EXTRACT(YEAR ,d.dateCreation)=2015", Dossier.class);
    System.out.println(strI);
    return query.getResultList();
}

我总是得到

在 EntityManager 中创建查询时发生异常: 异常描述:编译问题 [SELECT d FROM DOSSIER d WHERE EXTRACT(YEAR FROM d.dateCreation)=2015]。 [14, 21] 抽象模式类型“DOSSIER”是未知的。 [48, 62] 状态字段路径 'd.dateCreation' 无法解析为有效类型。

我直接在数据库中测试它,它可以工作

select * from dossier where extract(year from date_creation)=2015

我使用 jpaejbjdeveloper 作为 IDE。

【问题讨论】:

    标签: java jpa jpql


    【解决方案1】:

    首先,您的查询的主要问题是错误消息的内容:

    抽象模式类型“DOSSIER”未知

    由于 JPA 将您的 POJO 映射为实体,因此它们的名称区分大小写。您的查询应该是: SELECT d FROM Dossier d WHERE ...

    另外,关于您提到的问题,据我所知,EXTRACT 功能仅由 EclipseLink 支持。根据错误消息,我认为这是您的 JPA 实现,但如果不是,则有两种选择:

    1. 如果您使用的是 Hibernate,它具有用于检索日期部分的内置函数,例如 YEAR(date)MONTH(date)DAY(date)HOUR(date)MINUTE(date)SECOND(date)
    2. 对于任何其他 JPA 实现,或者如果您想使其符合 JPQL,您可以使用SUBSTRING:SUBSTRING(d.dateCreation, 1, 4) 解决。注意the first position of a string is denoted by 1;

    希望对你有帮助

    【讨论】:

    • 将 DATE 传递给 SUBSTRING 并没有什么“符合 JPQL”的规定。 SUBSTRING 仅用于字符串或算术表达式。
    • 它是,如果你希望它与任何实现兼容。
    • Errm,您似乎没有阅读我的评论。 SUBSTRING 只能接受标准化 JPQL 中的字符串或算术表达式。 DATE 两者都不是。
    • 也许你还没有读过我的。这是一种解决方法,我知道它们不是同一类型,但 substring 是所有实现共享的函数。
    • 哦,我读了你的答案和你的答案,答案明确地说“如果你想保持它符合 JPQL”,正如我所说的那样,它不符合 jpql 标准(因为 SUBSTRING 被支持为 FUNCTION,不一定支持接受日期)...所以不是“解决方法”。
    【解决方案2】:

    “直接在数据库中”称为SQL。

    createQuery 接受 JPQL 而不是 SQL,并且 YEAR / EXTRACT 是无效的关键字(尽管 YEAR,但不是 EXTRACT,一些 JPA 提供程序支持)。任何体面的 JPA 文档都会说明这一点。

    【讨论】:

      【解决方案3】:

      谢谢你们,我解决了这个问题: 首先,我得到了当前年份,而不是将其格式化为 int 而不是 String 以便进行比较并减去它这是我的代码,它工作正常:

          public List<Dossier> getAllDossierParAn() {
          Date date = new Date();
          Calendar calendar = new GregorianCalendar();
          calendar.setTime(date);
          int strI = calendar.get(Calendar.YEAR);
         String strInt  =Integer.toString(strI);
          String nvlstri= strInt.substring(2, 4);
          TypedQuery<Dossier> query;
          query = em.createQuery("SELECT d FROM Dossier d WHERE SUBSTRING(d.dateCreation, 7, 2) = :vr", Dossier.class);
        query.setParameter("vr",nvlstri);
         System.out.println("l anne est " +strI);
         System.out.println("la date formaté " +nvlstri);
          return query.getResultList();
      }
      

      【讨论】:

      • 你尝试过 YEAR() 方法吗?
      【解决方案4】:

      在 eclipselink 上,适合我的方式是这样的:

      SELECT  a.id, EXTRACT(WEEK CURRENT_DATE ) FROM Account a
      

      这至少适用于 postgres 和 sql server,但也应该适用于其他受支持的数据库。

      来自javadocs 支持的语法是:

      extract_expression ::= EXTRACT(date_part_literal [FROM] scalar_expression)
      

      FROM 似乎在 sql server 上引起了有趣的异常。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-09-11
        • 1970-01-01
        • 2016-08-02
        • 2016-07-27
        • 2021-10-02
        • 2018-02-16
        相关资源
        最近更新 更多