java - 如何使 Hibernate 自定义类型应用于聚合函数?
问题描述
我们正在更新一个 Hibernate (3.6) 应用程序,该应用程序定义了一个自定义货币类型,扩展org.hibernate.type.ImmutableType
. 让它改为扩展AbstractSingleColumnStandardBasicType
并创建一个 Java 类型描述符以存储Money
为BigInteger
.
但是,应用程序的各个部分都使用 HQL 查询,这些查询在货币字段上执行聚合函数(通常是 SUM)。旧样式 extendsImmutableType
会自动将结果转换为Money
,但是使用新样式时,不会发生这种情况;结果是一个 Long。
有谁知道如何让 Hibernate 自定义类型自动转换聚合函数的结果?
老用户类型:
public class MoneyUserType extends ImmutableType {
private final BigIntegerType bigIntegerType = new BigIntegerType();
@Override
public Object fromStringValue(final String string) {
final BigInteger bigInteger = (BigInteger) bigIntegerType.fromStringValue(string);
return Money.inCents(bigInteger);
}
@Override
public Object get(final ResultSet rs, final String name) throws SQLException {
final BigInteger bigInteger = (BigInteger) bigIntegerType.get(rs, name);
if (null == bigInteger) {
return null;
}
return Money.inCents(bigInteger);
}
@Override
public void set(final PreparedStatement st, final Object object, final int index) throws SQLException {
final Money money = (Money) object;
bigIntegerType.set(st, money.getAmountInCents(), index);
}
@Override
public int sqlType() {
return bigIntegerType.sqlType();
}
@Override
public String toString(final Object object) {
final Money money = (Money) object;
return bigIntegerType.toString(money.getAmountInCents());
}
public String getName() {
return Money.class.getName();
}
@SuppressWarnings("unchecked")
public Class getReturnedClass() {
return Money.class;
}
}
新用户类型:
public class MoneyUserType extends AbstractSingleColumnStandardBasicType<Money> {
public MoneyUserType() {
super(BigIntTypeDescriptor.INSTANCE, MoneyJavaTypeDescriptor.INSTANCE);
}
@Override
public String getName() {
return Money.class.getName();
}
}
public class MoneyJavaTypeDescriptor extends AbstractTypeDescriptor<Money> {
public static final MoneyJavaTypeDescriptor INSTANCE = new MoneyJavaTypeDescriptor();
public MoneyJavaTypeDescriptor() {
super(Money.class, ImmutableMutabilityPlan.INSTANCE);
}
@Override
public Money fromString(final String string) {
final BigInteger bigInteger = BigIntegerTypeDescriptor.INSTANCE.fromString(string);
return Money.inCents(bigInteger);
}
@Override
public <X> X unwrap(Money value, Class<X> type, WrapperOptions options) {
if (value == null) {
return null;
}
if (type.isAssignableFrom(BigInteger.class)) {
return (X) value.getAmountInCents();
}
if (type.isAssignableFrom(Long.class)) {
return (X) Long.valueOf(value.getAmountInCents().longValue());
}
if (type.isAssignableFrom(Integer.class)) {
return (X) Integer.valueOf(value.getAmountInCents().intValue());
}
throw unknownUnwrap(type);
}
@Override
public <X> Money wrap(X value, WrapperOptions options) {
if (value == null) {
return null;
}
if (Number.class.isInstance(value)) {
return Money.inCents((Number) value);
}
throw unknownWrap(value.getClass());
}
@Override
public String toString(final Money money) {
return BigIntegerTypeDescriptor.INSTANCE.toString(money.getAmountInCents());
}
}
解决方案
您可以将INSTANCE
静态字段添加到您的MoneyUserType
:
public class MoneyUserType extends AbstractSingleColumnStandardBasicType<Money> {
public static final MoneyUserType INSTANCE = new MoneyUserType();
// ...
}
然后将例如以下函数添加到您的自定义休眠方言中:
public class MyPostgreSQLDialect extends PostgreSQL10Dialect
{
public MyPostgreSQLDialect()
{
registerFunction("sum_money", new StandardSQLFunction("sum", MoneyUserType.INSTANCE));
}
}
persistence.xml
用你的或声明这个方言hibernate.cfg.xml
然后您将能够sum_money
在您的 hql 中使用该功能:
Money sum = entityManager.createQuery(
"select sum_money(m.money) from MoneyEntity m",
Money.class
).getSingleResult();
推荐阅读
- c# - 我将如何使用下载的字符串进行用户输入?
- vue.js - 如何在 Nuxt.js 中所有打开的选项卡上触发特定操作
- python - 如何正确使用 Python 从 xmsd2 读取 .h5 文件?
- kubernetes - 无法使用 Helm 安装入口合并
- mysql - 如何使用 MySQL OUTER JOIN 单独分组的表
- azure-pipelines - 使用管道自动创建 Azure VM 的最佳方法是什么?
- python - 如何使用烧瓶(表格、饼图等)在页面上获取多个元素
- powershell - Get-ADObject:解析查询时出错 不支持:-neq'?
- mysql - 如何获取组的最新记录
- javascript - 内联网格 kendoComboBox 在 javascript 中获取值