Итак, на самом деле предположение о том, что мой пользовательский тип хорош, не так верно.
Я понял, что это что-то вроде копий спящего режима YesNo, поэтому я был уверен ...
Но это не так.
Проблема заключалась в том, что методы сборки и разборки не были согласованными.
При дизассемблере значение (здесь Boolean) было преобразовано в строку следующим фрагментом:
@Override
public Serializable disassemble(Object value) {
return (value == null) ? null : value.toString();
}
но в сборке строка осталась «как есть» следующим фрагментом:
@Override
public Object assemble(Serializable cached, Object owner) {
return (cached == null) ? null : cached;
}
правильная реализация:
@Override
public Object assemble(Serializable cached, Object owner) {
if(cached == null) {
return null;
}
if(cached.equals("true")) {
return true;
}
return false;
}
Поскольку пара методов сборки/дизассемблирования не использовалась до тех пор, пока в кеше не выполнялась какая-либо сериализация, ошибка не обнаруживалась до тех пор, пока не использовала приложение, использующее кеш второго уровня.
При «регулярной» загрузке объекта из базы данных, AstractEntityPersister # hydrate вызывается loadFromResultSet (строка 1527 org.hibernate.loader.Loader)
гидрат выполняет индивидуальный диалог, вызывая nullSafeGet по типу
При попадании в кэш запись кэша «расщепляется» по org.hibernate.cache.entry.StructuredCacheEntry # destructure, а затем собирается командой assemblyCacheEntry. В какой-то момент он вызывает метод «собрать» пользовательского типа.
Обратите внимание, что для эффективности я постараюсь избежать сравнения строк, но вы получите идею ... :-)