Вопрос

Есть ли способ использовать объекты Flyweight с отображением сохраняемости в режиме гибернации?Моя модель данных содержит много объектов, которые будут одинаковыми.Вместо того чтобы иметь отдельный экземпляр для каждого из этих одних и тех же объектов, я бы хотел использовать шаблон проектирования Flyweight и ссылаться всегда на один и тот же физический объект.Как добиться этого в режиме гибернации?

Кстати.все ли JVM оптимизируют использование строк таким образом, что когда одна и та же строка используется несколько раз, это всегда будет один и тот же физический экземпляр?

Это было полезно?

Решение

Это зависит от обстоятельств.

Только для чтения ценности вы можете легко реализовать шаблон flyweight, создав пользовательский UserType, который будет каждый раз возвращать объекты из пула вместо новых экземпляров.

Для сущностей Hibernate по умолчанию является нормальным и хочет быть согласованным между транзакциями и, следовательно, не будет совместно использовать сущности между сеансами, чтобы избежать условий гонки ваших данных - и я не думаю, что это то, чего вы хотите.

Но в случае, если это так (а это совершенно не рекомендуется, не зная толком, что вы делаете), вы можете реализовать Interceptor.getEntity(), который предназначен для кэширования второго уровня.В этом методе вы можете вернуть объект (даже тот, который является общим для других сеансов), и у вас фактически будет шаблон flyweight для ваших объектов.

НО я настоятельно рекомендую воздержаться от этого для обеспечения согласованности ваших данных - гораздо лучше иметь фактические неизменяемые значения flyweight, на которые ссылаются объекты, чем также пытаться использовать flyweight для реальных объектов.

Другие советы

Да, вы можете реализовать шаблон Flyweight с помощью Hibernate.

Шаблон flyweight - это способ минимизировать использование памяти для каждого экземпляра.Стратегия заключается в том, чтобы разделить как можно больше состояний между экземплярами с минимальным весом.В вашем случае общим состоянием является все, кроме идентификатора объекта hibernate и некоторого дополнительного состояния для поддержания идентичности объекта.

Каждому экземпляру с минимальным весом нужен свой собственный идентификация объекта.Дополнительное состояние - это способ реализации идентификации для различения объектов, которые имеют общее состояние.

public boolean equals(Object obj){
  Fly other; [..]//check type
  //null checks ommitted
  return other.myState.equals(myState) && other.commonState.equals(commonState); 
}

Если идентификатор объекта является общим для экземпляров, hibernate будет интерпретировать все физические экземпляры (ссылки) как один и тот же экземпляр.Hibernate использует метод equals для проверки подлинности объекта, и ваша реализация equal должна была бы вернуть (! a.equals(a) == true) что является незаконным. Равный должен быть рефлексивным.Если вы разорвете этот контракт, все библиотеки, которые зависят от контракта, будут разорваны (коллекции, гибернация и т.д.).

Вы не можете реализовать метод equal, используя идентификатор объекта hibernate различать объекты.Это сделало бы идентификацию объекта зависимой от состояния сохраняемости (persistented или transient).

Одним из способов моделирования общего состояния в hibernate является связь "один ко многим" между объектами общего состояния и объектами с наименьшим весом.(Может быть, у кого-то есть идея, как сопоставить данные без объединения двух таблиц?)

Строка:Только интернализованные строки будут разделены.В большинстве случаев это не самое лучшее решение.Это подходит для символов (имя класса, имя метода и т.д.).Интернализованные строки никогда не будут собраны мусором, и у вас должен быть экземпляр String, который в любом случае будет собран мусором new String("..").intern().Это не сэкономит выделенные средства.Существует лишь незначительное преимущество в том, что базовая строка не переживет генерацию gc или может быть выделена в стеке (при включенном и применимом escape-анализе в hot spot).

все ли JVM оптимизируют использование строк таким образом, что когда одна и та же строка используется несколько раз, это всегда будет один и тот же физический экземпляр?

Я очень в этом сомневаюсь.В том же файле класса, когда определено как:

String s1 = "Yes";
String s2 = "Yes";

вероятно, у вас будет s1 == s1.

Но если у вас есть такие:

String x = loadTextFromFile(); // file contains es
StringBuilder b = new StringBuilder();
s2 = b.append("Y").append(x).toString(); // s2 = "Yes"

Я не думаю, что среда выполнения собирается проверять и сравнивать все загруженные строки с возвращаемым значением them builder.

Итак, всегда сравнивайте объекты с помощью equals().В любом случае, это хороший совет, поскольку каждый хороший совет начинается с:

if (this == o) {
    return true;
}

Если ваши объекты реализуют равенство по идентификатору, Hibernate будет иметь только один экземпляр, связанный с этим первичным ключом.Я не думаю, что это точно такая же идея, как Flyweight, но дело в том, что у вас не будет много экземпляров одного и того же объекта Hibernate .

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top