JPA/Hibernate + HQL/JPQL: select DTO with BigDecimal parameter

独自空忆成欢 提交于 2019-12-14 02:34:08

问题


We are using JPA with hibernate as the implementation. Suppose I have the following DTO:

public class SupplierInfoDto{
   private String supplierName;
   private BigDecimal remainingFinances;

   public SupplierInfoDto(String supplierName, BigDecimal remainingFinances){
       this.supplierName = supplierName;
       this.remainingFinances = remainingFinances;
   }

   // getters / setters
}

I cannot seem to get hibernate to properly find this constructor. I first tried the following query (the model is more complicated than this, and I need to fetch some aggregations eventually (not directly on the entities), that's why I'm fetching a DTO instead of the entities):

SELECT NEW com.company.dto.SupplierInfoDto(s.name, f.remaining)
FROM Supplier s INNER JOIN Finances f
WHERE s.id = :SupplierId

However, I get a org.hibernate.hql.ast.QuerySyntaxException: Unable to locate appropriate constructor on class exception.

The remaining column I'm selecting from is stored as a float in MSSQL (I know, I know money should never be stored as floats, but this is an existing system where I cannot just change this datatype)..

As a test, I tried the following query, but with the same exception as above:

SELECT NEW com.company.dto.SupplierInfoDto(s.name, NEW java.math.BigDecimal(10))
FROM Supplier s
WHERE s.id = :SupplierId

So my question is: How do I make hibernate/JPA find the appropriate constructor for the two queries above?

UPDATE: The remaining property is of type double on the Finances entity (not my decision).


回答1:


I am not sure why the BigDecimal ctor is not being recognised but you could overload your constructors

If you had

public SupplierInfoDto(String s, Double d) {
   this(s, new BigDecimal(String.valueOf(d)));
}

public SupplierInfoDto(String s, BigDecimal bd) {
   //set fields
}

Not that if you use the BigDecimal double constructor the number is based on a double so can still have rounding errors. It is usually best to use BigDecimal string contstrctor

For example

new BigDecimal("0.1")

is more precise than

new BigDecimal(0.1d)

This article explains this




回答2:


class named X  with a constructor that takes two parameters. The types of the parameters from the SELECT clause must match the signature defined in the class.

Syntax for the SELECT clause:

select_clause ::= SELECT [DISTINCT] select_expression
    {, select_expression}*
    select_expression ::=
    single_valued_path_expression |
    aggregate_expression |
    identification_variable |
    OBJECT(identification_variable) |
    constructor_expression
    constructor_expression ::=
    NEW constructor_name ( constructor_item {, constructor_item}* )
    constructor_item ::= single_valued_path_expression |
    aggregate_expression
    aggregate_expression ::=
    { AVG | MAX | MIN | SUM }
    ([DISTINCT] state_field_path_expression) |
    COUNT ([DISTINCT] identification_variable |
    state_field_path_expression |
    single_valued_association_path_expression)



回答3:


Why not use java.lang.Number as the constructor parameter and create the BigDecimal field based on the .floatValue() / doubleValue() of the parameter.



来源:https://stackoverflow.com/questions/12742345/jpa-hibernate-hql-jpql-select-dto-with-bigdecimal-parameter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!