如何让hibernate在属性

时间:2015-07-24 09:41:31

标签: java hibernate

对于某些实体,我们需要将负载(数千个)分离的内容永久保存在内存中。它们的许多属性来自一组有限的字符串(尽管不足以将其置于枚举中)。是否有可能让hibernate使用String.intern来保存空间?

理想情况下,应该通过注释工作,我可以放在每个属性上,或者可以轻易更改的内容,而不会过多地混淆源代码。

3 个答案:

答案 0 :(得分:1)

1)您可以对关键属性使用属性访问,并在setter中使用字符串:

public void setFoo(String foo) {
   this.foo = foo != null ? foo.intern() : null;
}

2)如果上述解决方案繁琐(您可能拥有大量此类String属性),那么您可以使用反射注册Hibernate interceptor并实习所有String字段:

for (Field field : getDeclaredFields(entity)) {
    if (!isStaticOrFinal(field)) {
        field.setAccessible(true);
        Object value = field.get(entity);
        if (value instanceof String) {
            field.set(entity, ((String) value).intern());
        }
    }
}

private List<Field> getDeclaredFields(Object object) {
    List<Field> result = new ArrayList<Field>(Arrays.asList(object.getClass().getDeclaredFields()));
    for (Class<?> superclass = object.getClass().getSuperclass(); superclass != null; superclass = superclass.getSuperclass()) {
        result.addAll(Arrays.asList(superclass.getDeclaredFields()));
    }
    return result;
}

private boolean isStaticOrFinal(Field field) {
    return ((Modifier.STATIC | Modifier.FINAL) & field.getModifiers()) != 0;
}

您可以在onSaveonLoad拦截器方法中执行此操作。

答案 1 :(得分:1)

正如您自己建议的那样,使用JPA属性转换器完全可行。您可以在转换器上使用autoApply = true在一般级别上执行此操作,也可以使用@Convert注释在字段级别上执行此操作。

import javax.persistence.AttributeConverter;
import javax.persistence.Converter;

@Converter(autoApply = true)
public class StringInternConverter implements AttributeConverter<String, String> {
    @Override
    public String convertToDatabaseColumn(String attribute) {
        return attribute;
    }

    @Override
    public String convertToEntityAttribute(String dbData) {
        return dbData != null? dbData.intern(): null;
    }
}

使用Hibernate 5.2.10测试并且像魅力一样工作!

答案 2 :(得分:0)

可能还可以实现一个JPA Attribute Converter,它只对属性调用String.intern(),并使用@Convert(StringInternConverter.class)注释属性。