How to use hibernation for String.intern by attributes

For some objects, we need to constantly store loads (thousands) of individual items in memory. Many of their attributes are limited to stringset (though not limited to this to translate it into an enumeration). Can hibernate String.intern be used for these attributes to save space?

Ideally this should work with an annotation that I could apply to each of these attributes or something easily changeable without obfuscating the source code too much with this issue.

+3


source to share


3 answers


As you suggest yourself, it does a great job with the JPA Attribute Converter. You can do this on a general level using autoApply = true

on a converter, or you can do it on a field by field using an annotation @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!

+1


source


1) You can use property access for critical properties and put strings in setters:

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

      

2) If the above solution is tedious (you can have many properties like this String

), you can register a Hibernate interceptor and expose all fields String

using reflection:



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 accomplish this in the interceptor methods onSave

and onLoad

.

+1


source


It is probably also possible to implement JPA Attribute converter which simply calls String.intern () on the attributes and annotate the attributes with @Convert(StringInternConverter.class)

.

0


source







All Articles