简体   繁体   English

休眠如何在属性上使用String.intern

[英]How to have hibernate use String.intern on attributes

For some entities we need to keep loads (thousands) of detached enties permanently in memory. 对于某些实体,我们需要将成千上万个独立实体的负载永久保存在内存中。 Many of their attributes are from a limited set of strings (though not limited enough to put it into an enumeration). 它们的许多属性来自一组有限的字符串(尽管不足以将其放入枚举中)。 Is it possible to have hibernate use String.intern for those attributes to save space? 休眠是否可以将String.intern用于这些属性以节省空间?

Ideally that should work via an annotation I could put on each of those attributes, or something easily changeable, without confusing the source code too much by this implementation concern. 理想情况下,这应该通过注释来实现,我可以将这些属性中的每一个或易于更改的属性放在注释上,而不会因实现问题而使源代码过于混乱。

As you suggest yourself, it's perfectly doable with a JPA attribute converter. 正如您自己建议的那样,使用JPA属性转换器完全可以实现。 You could do it on a general level by using autoApply = true on the converter, or you could do it on a field by field level with the @Convert annotation. 您可以在转换器上使用autoApply = true在一般级别上执行此操作,也可以在具有@Convert批注的逐字段级别上进行@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;
    }
}

Tested with Hibernate 5.2.10 and works like a charm! 经过Hibernate 5.2.10的测试,就像魅力一样!

1) You can use property access for the critical properties and intern the strings in the setters: 1)您可以对关键属性使用属性访问,并在设置器中内插字符串:

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

2) If the above solution is tedious (you may have lots of such String properties), then you could register a Hibernate interceptor and intern all of the String fields using reflection: 2)如果上述解决方案很繁琐(您可能有很多此类String属性),则可以注册一个Hibernate拦截器并使用反射来实习所有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;
}

You can execute this in the onSave and onLoad interceptor methods. 您可以在onSaveonLoad拦截器方法中执行此操作。

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

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

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