对于某些实体,我们需要将负载(数千个)分离的内容永久保存在内存中。它们的许多属性来自一组有限的字符串(尽管不足以将其置于枚举中)。是否有可能让hibernate使用String.intern来保存空间?
理想情况下,应该通过注释工作,我可以放在每个属性上,或者可以轻易更改的内容,而不会过多地混淆源代码。
答案 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;
}
您可以在onSave
和onLoad
拦截器方法中执行此操作。
答案 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)
注释属性。