简体   繁体   English

如何转换 JPA 标准表达式<long>长 java 型</long>

[英]How do I cast JPA criteria Expression<Long> to long java type

This code这段代码

    criteriaBuilder.literal(LocalDateTime.now().minusDays( (long) root.get("person").get("birthDay").as(Long.class)))  

has not compile error but at run time gets this error:没有编译错误但是在运行时得到这个错误:
Cannot cast from Expression to int无法从 Expression 转换为 int

I tried using String:我尝试使用字符串:

    criteriaBuilder.literal(LocalDateTime.now().minusDays( Long.parseValue( root.get("person").get("birthDay").toString())))  

This also gets error:这也会出错:
ERROR: For input string: "org.hibernate.query.criteria.internal.path.SingularAttributePath@2ed2d35d";错误:对于输入字符串:“org.hibernate.query.criteria.internal.path.SingularAttributePath@2ed2d35d”; nested exception is java.lang.NumberFormatException: For input string: "org.hibernate.query.criteria.internal.path.SingularAttributePath@2ed2d35d"嵌套异常是 java.lang.NumberFormatException:对于输入字符串:“org.hibernate.query.criteria.internal.path.SingularAttributePath@2ed2d35d”

I think you are mixing different concepts.我认为您正在混合不同的概念。

Please, be aware that when using the JPA related artifacts is important to understand that they are objects that define expressions that may represent, when computed, a certain value of a certain type in the database, but when you are constructing your JPA criteria queries, they are just that, artifacts for your JPA criteria queries.请注意,在使用 JPA 相关工件时,重要的是要了解它们是定义表达式的对象,这些表达式在计算时可能表示数据库中某种类型的某个值,但是当您构建 JPA 条件查询时,它们就是您的 JPA 标准查询的工件。

Now consider the following expression you are trying using:现在考虑您尝试使用的以下表达式:

root.get("person").get("birthDay").toString()

As a result of the evaluation of this code you will get a String representation of the JPA criteria path you are defining, org.hibernate.query.criteria.internal.path.SingularAttributePath@2ed2d35d in your use case.作为评估此代码的结果,您将在用例中获得org.hibernate.query.criteria.internal.path.SingularAttributePath@2ed2d35d标准路径的String表示形式,即 org.hibernate.query.criteria.internal.path.SingularAttributePath@2ed2d35d。

Then, if you compute Long.parseValue of org.hibernate.query.criteria.internal.path.SingularAttributePath@2ed2d35d if will raise an error because org.hibernate.query.criteria.internal.path.SingularAttributePath@2ed2d35d doesn't represent a valid number.然后,如果您计算Long.parseValueorg.hibernate.query.criteria.internal.path.SingularAttributePath@2ed2d35d会引发错误,因为org.hibernate.query.criteria.internal.path.SingularAttributePath@2ed2d35d不代表 a有效号码。

It is unclear by your question what you are actually trying to achieve but the JPA criteria API provides a rich set of builtin expressions you can use as Predicate s to deal with dates, such as, assuming root.get("person").get("birthDay") represent a Date like object:您的问题不清楚您实际上想要实现什么,但 JPA 标准 API 提供了一组丰富的内置表达式,您可以将其用作Predicate来处理日期,例如,假设root.get("person").get("birthDay")表示object 这样的Date

cb.greaterThanOrEqualTo(root.get("person").get("birthDay"), cb.literal(LocalDate.now()));
//...
cb.greaterThan(root.get("person").get("birthDay"), cb.literal(LocalDate.now()));
//...
cb.lessThanOrEqualTo(root.get("person").get("birthDay"), cb.literal(LocalDate.now()));
//...
cb.lessThan(root.get("person").get("birthDay"), cb.literal(LocalDate.now()));

You can create your own function using cb.function as well and use that function in your predicates.您也可以使用cb.function创建自己的 function 并在谓词中使用该 function。 Consider for that purpose defining a helper method somewhere in your code, for example:为此考虑在代码中的某处定义一个辅助方法,例如:

public static Expression<Long> daysBetween(
  CriteriaBuilder cb, Expression<LocalDate> startDate, Expression<LocalDate> endDate) {
  return cb.function("DAYS_BETWEEN", long.class, startDate, endDate);
}

Where DAYS_BETWEEN is the name, you can choose the one you consider most appropriate, of a database level predefined or user defined function.其中DAYS_BETWEEN是名称,您可以选择您认为最合适的名称,即预定义的数据库级别或用户定义的 function。 In Oracle for example it exists per se , but it should be straight forward to implement in other database systems:例如,在 Oracle 中,它本身就存在,但在其他数据库系统中实现起来应该很简单:

create or replace function days_between...

Then, use this helper method in your code.然后,在您的代码中使用此辅助方法。 For example, give me the persons that turns years in the following 10 days :例如,给我在接下来的 10 天内年满岁的人

cb.and(
  cb.lessThan(
    daysBetween(cb, root.get("person").get("birthDay"), cb.literal(LocalDate.now()) ),
    cb.literal(10)
  )
)

I haven't used this, I found the relevant documentation, I think it seems to be available like the following, just to provide a reference, I hope it can help you.这个我没用过,找了相关的文档,我觉得好像有下面这样的,只是提供一个参考,希望对你有帮助。

literal(T) 字面量(T)

在此处输入图像描述

Integer a = 1;
Long b = 2L;
String c = "3";
Expression<Integer> integerParameter = criteriaBuilder.literal(a);
Expression<Long> longParameter = criteriaBuilder.literal(b);
Expression<String> stringParameter = criteriaBuilder.literal(c);

And i found that method minusDays(long) return a LocalDateTime , so i think we should take that like:我发现该方法minusDays(long)返回一个LocalDateTime ,所以我认为我们应该像这样:

LocalDateTime ldt = LocalDateTime.now().minusDays( (long) root.get("person").get("birthDay").as(Long.class));
Expression<LocalDateTime> longParameter = criteriaBuilder.literal(ldt);

As for how to convert LocalDateTime into the data you need, I am currently unclear, because it is not clear what your specific needs are.至于如何将 LocalDateTime 转换成你需要的数据,我目前还不清楚,因为不清楚你的具体需求是什么。

Point is here.重点在这里。 Look at the error message,maybe it is not Long.看错误信息,可能不是Long。

java.lang.NumberFormatException: For input string: "org.hibernate.query.criteria.internal.path.SingularAttributePath@2ed2d35d" java.lang.NumberFormatException:对于输入字符串:“org.hibernate.query.criteria.internal.path.SingularAttributePath@2ed2d35d”

Please check value for请检查值

root.get("person").get("birthDay")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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