【问题标题】:Calculating age from birthdate with @Formula使用@Formula 从出生日期计算年龄
【发布时间】:2017-07-05 17:45:14
【问题描述】:

我正在尝试使用@Formula 从她的生日计算用户的年龄。

根据MySQL documentation,我试过这个:

@Entity
@Table(name = "users")
public final class UserProfile {

   //this column is called BIRTHDATE in database
   private String birthdate;

    @Formula("(select TIMESTAMPDIFF(YEAR,BIRTHDATE,CURDATE()) from users)")
    private String age;

    //more things...

}

但我得到一个错误:

java.sql.SQLSyntaxErrorException:您的 SQL 中有错误 句法;检查与您的 MariaDB 服务器相对应的手册 在附近使用正确语法的版本 'userprofil0_.YEAR,userprofil0_.BIRTHDATE,CURDATE()) 来自用户)作为 第 1 行的公式 0_0_ f'

如果我在 phpMyAdmin 中执行该查询,它会正常工作。

this之后,我也尝试过:

@Formula("date_part('year', age(birthdate))")
private String age; //I tried with int instead of String, too

但我有这个错误:

java.sql.SQLSyntaxErrorException: FUNCTION userprofile-service-db.date_part 不存在

即使在 phpMyAdmin 中这个也不起作用...

有什么想法吗?

编辑

我刚刚尝试过:

@Formula("(TIMESTAMPDIFF(YEAR,BIRTHDATE,CURDATE()))")
private String age;

但仍然无法正常工作。这是 Hibernate 显示的查询:

 select
        userprofil0_.id as id1_1_0_,
        userprofil0_.about_me as about_me2_1_0_,
        userprofil0_.birthdate as birthdat3_1_0_,
        userprofil0_.display_name as display_4_1_0_,
        userprofil0_.email as email5_1_0_,
        userprofil0_.profile_photo as profile_6_1_0_,
        (TIMESTAMPDIFF(userprofil0_.YEAR,
        userprofil0_.BIRTHDATE,
        CURDATE())) as formula0_0_ 
    from
        users userprofil0_ 
    where
        userprofil0_.id=?

看起来Hibernate 将YEAR 作为一个列,但实际上它是一个保留字。如果我在 phpMyAdmin 中执行该查询,只用 YEAR 替换 userprofil0_.YEAR,它工作正常。

【问题讨论】:

  • 嗨!我更新了我的答案。你试过了吗?

标签: java hibernate mariadb


【解决方案1】:

您的第一次尝试几乎是正确的,但您不需要 selectfrom 部分,因为列 BITHDATE 在同一个表中:

@Formula("(TIMESTAMPDIFF(YEAR,BIRTHDATE,CURDATE()))")
private String age;

打开生成的 SQL 查询的日志记录也很有用(在 Hibernate 中,通过将属性 show_sql 设置为 true 来完成),以查看整个查询。

更新

作为 Hibernate 将 YEAR 视为列名的一种解决方法,您可以在自定义 MySQL 函数中包装对 TIMESTAMPDIFF 的调用,并在公式中调用此函数。这是针对类似问题的 SO answer

另一种解决方案可能是编写自定义方言解析器,它将 YEAR 视为关键字:SO answer

【讨论】:

  • 感谢您的回答。我已经尝试过你的解决方案。检查我的编辑。貌似Hibernate是把YEAR作为表的一列,其实是保留字
  • 您是否尝试将YEAR 括在单引号'YEAR' 或反引号YEAR 中?
  • 是的,两者都有。使用单引号,查询崩溃和使用反引号,它也被视为表列
  • 奇怪,因为根据这个gist反引号(`)应该做的工作
  • 谢谢,我已经创建了一个函数,现在它运行良好!
【解决方案2】:

试试这个公式来计算当前日期和数据库中存储的 BIRTHDATE 列之间的差异,以获取用户的年龄

@Formula("YEAR(CURDATE()) - YEAR(BIRTHDATE)")
private int age;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-31
    • 1970-01-01
    • 2023-03-19
    相关资源
    最近更新 更多