Hibernate и Flyweight - PullRequest
       31

Hibernate и Flyweight

7 голосов
/ 29 ноября 2009

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

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

Ответы [ 4 ]

3 голосов
/ 29 ноября 2009

Это зависит.

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

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

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

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

2 голосов
/ 29 ноября 2009

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

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

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

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

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

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

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

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

1 голос
/ 29 ноября 2009

все ли 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"

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

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

if (this == o) {
    return true;
}
0 голосов
/ 29 ноября 2009

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

...