Вопрос

Мы создали слой кэширования для нашего J2EE-приложения.В этом случае мы используем Ehcache.Это создало несколько проблем.

Давайте возьмем этот пример.

OrderItem orderitem = cache.getOrderItemByID("id");
OrderItem old_orderitem = cache.getOrderItemID("id");

orderitem.setStatus(1);
old_orderitem.setStatus(2);

Если мы не будем осторожны, любые изменения, внесенные в любой из этих объектов, повлияют на другой (они ссылаются на один и тот же объект).Сохранение orderitem обратно в базу данных придало бы ему статус = 2

Как бы мы решили это наилучшим образом?

Мы попытались создать метод .copyObject() для каждого объекта.Который просто создает новый объект и устанавливает все значения.Но это не кажется хорошим решением.

Этот пример был просто для иллюстрации.Код намного сложнее этого, но результат тот же.

********************** Обновление от 15.07.2010 **************************************************

В EHCache 2 есть несколько опций для включения copyRead() и copyWrite().И это решает все мои проблемы :)

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

Решение

Это проблема с изменяемым состоянием.Это не только кэширование, это любое время, когда у вас может быть несколько ссылок на один и тот же объект, и этот объект является изменяемым.Например:

HashMap map = new HashMap();
map.put("one", new OrderItem());
OrderItem one = map.get("one");
OrderItem two = map.get("one");
one.setStatus(1);
two.setStatus(2);

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

Вы правы, рассматривая возможность копирования объекта.Ваши варианты следующие:

У каждого из них есть свои сильные и слабые стороны, и какой из них работает лучше всего, будет зависеть от вашего окружения.

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

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

Если это так, то ваш пользовательский уровень кэширования (вокруг ehcache) должен создавать объект из данных кэша, когда пользователь делает запрос - это каждый раз будет выдавать вам уникальный объект, и вы не будете получать помехи от объекта.

Когда вы извлекаете из кэша по идентификатору (getOrderItemById), я бы предположил, что это означает "получить объект уникальный идентифицируется по id=?".Во втором отрывке у вас есть (или пытаетесь иметь?) 2 разных объекта, так что это немного похоже на то, что вы пытаетесь сделать 2 противоречивые вещи в коде.

Вы могли бы обеспечить уникальность -Id="ID" всегда является одним и тем же объектом.Если вы установили статус, а затем сбросили его, это означает, что тот же объект имеет новый статус.Вероятно, вы хотели бы расширить метод .equals, чтобы возвращать true, если идентификатор также совпадает.

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

Создание копии - тоже неплохой способ справиться с этим, хотя неясно, что значит иметь 2 объекта, работающих с одним и тем же идентификатором.Может быть, копия должна быть создана с нулевым идентификатором, чтобы указать, что она еще не существует в кэше?

Каково правильное поведение для вашего приложения?

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

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

Однако проблема изменчивого состояния, как упоминает Джейми Маккриндл, никуда не исчезает.

Ссылка: http://ehcache.org/documentation/explicitlocking.html

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