简体   繁体   English

转换@Query MonetaryAmount 结果

[英]Convert @Query MonetaryAmount result

I just converted all of my java.math.BigDecimal usages to javax.money.MonetaryAmount (where they represented money).我刚刚将我所有的java.math.BigDecimal用法转换为javax.money.MonetaryAmount (它们代表金钱)。 I am currently "assuming" the currency to be USD with the help of a MoneyUtils to avoid adding extra database columns that will only contain "USD" in them.我目前在MoneyUtils的帮助下“假设”货币为 USD,以避免添加仅包含“USD”的额外数据库列。 This can be seen in the next 2 snippets.这可以在接下来的 2 个片段中看到。

@Converter(autoApply = true)
public class MonetaryAmountConverter
        implements AttributeConverter<MonetaryAmount, BigDecimal> {

    @Override
    public BigDecimal convertToDatabaseColumn(final MonetaryAmount monetaryAmount) {
        return DefaultUtils.defaultOrNull(
                monetaryAmount,
                ma -> ma.getNumber().numberValue(BigDecimal.class));
    }

    @Override
    public MonetaryAmount convertToEntityAttribute(final BigDecimal monetaryAmountValue) {
        if (monetaryAmountValue == null) {
            return null;
        } else {
            return MoneyUtils.of(monetaryAmountValue);
        }
    }
}
public final class MoneyUtils {
    public static final CurrencyUnit DOLLAR = Monetary.getCurrency(Locale.US);
    public static MonetaryAmount of(@NonNull final BigDecimal value) {
        return Money.of(value, MoneyUtils.DOLLAR);
    }
}

I have this @Repository method that should give me a sum, which could be null if no rows match:我有这个@Repository方法应该给我一个总和,如果没有行匹配,它可能是null

@Query("query that can return null or a numeric")
MonetaryAmount sumSomeData();

The problem is that it doesn't go through my MonetaryAmountConverter .问题是它没有通过我的MonetaryAmountConverter go 。 I tried adding a @Convert directly to the method but it didn't work.我尝试将@Convert直接添加到该方法,但它没有用。

@Query("query that can return null or a numeric")
@Convert(converter = MonetaryAmountConverter.class)
MonetaryAmount sumSomeData();

So it appears that an AttributeConverter with @Converter(autoApply = true) applies to JPA Entity fields, but not to method return types, even when @Convert is added to the method signature.因此,带有@Converter(autoApply = true)AttributeConverter似乎适用于 JPA 实体字段,但不适用于方法返回类型,即使将@Convert添加到方法签名中也是如此。

  • Is there something I am missing?有什么我想念的吗?
  • Is there a way to do this without needing to do the conversion manually in the caller of this repository method?有没有一种方法可以做到这一点,而无需在此存储库方法的调用者中手动进行转换?

You can use a constructor expression :您可以使用构造函数表达式

The SELECT clause identifies which objects and values to return as the query results. SELECT 子句标识要作为查询结果返回的对象和值。 The expressions discussed in Section 11.4, “Expressions” are all valid select expressions, except where otherwise noted. 第 11.4 节“表达式”中讨论的表达式都是有效的 select 表达式,除非另有说明。 See the section Section 11.10, “Query API” for information on handling the results depending on the types of values specified in the SELECT clause.有关根据 SELECT 子句中指定的值类型处理结果的信息,请参阅第 11.10 节“查询 API”部分。

There is a particular expression type that is only valid in the select clause.有一个特定的表达式类型仅在 select 子句中有效。 Hibernate calls this “dynamic instantiation”. Hibernate 将此称为“动态实例化”。 JPQL supports some of that feature and calls it a “constructor expression” JPQL 支持其中的一些功能并将其称为“构造函数表达式”

General example:一般示例:

select new Person(user.name, address)
from User as user
left join user.address as address

Before you ask, no, you cannot call methods, only constructors.在你问之前,不,你不能调用方法,只能调用构造函数。 Also, you'll need to consider the fact that your query may return null .此外,您需要考虑您的查询可能返回null的事实。 You could write a wrapper class.您可以编写一个包装器 class。

public final class MonetaryAmountWrapper {
  public MonetaryAmountWrapper(final BigDecimal value) {
    this.monetaryAmount = Money.of(value, MoneyUtils.DOLLAR);
  }

  private final MonetaryAmount monetaryAmount;
}

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

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