如何解决如何使Hibernate自定义类型应用于聚合函数?
我们正在更新一个Hibernate(3.6)应用程序,该应用程序定义了一种货币自定义类型,并扩展了org.hibernate.type.ImmutableType
。使它扩展AbstractSingleColumnStandardBasicType
并创建Java类型描述符以将Money
存储为BigInteger
相当简单。
但是,应用程序的各个部分都使用HQL查询,这些查询对money字段执行汇总功能(通常是SUM)。扩展为ImmutableType
的旧样式会自动将结果转换为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());
}
}
解决方法
我们可以通过在DTO上添加额外的setter并按照Custom type / converter in conjunction with Hibernate's Transformers.aliasToBean
在查询中添加别名来解决此问题这不是理想的方法,但可以使其正常工作。
,您可以将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
中声明该方言
然后您将可以在您的hql中使用sum_money
函数:
Money sum = entityManager.createQuery(
"select sum_money(m.money) from MoneyEntity m",Money.class
).getSingleResult();
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。