Ссылки на объект Java со слоем кэша

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

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

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

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

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

Как мы решили бы это лучший способ?

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

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

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

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

5
задан Tommy 15 July 2010 в 13:59
поделиться

3 ответа

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

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);

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

Вы правы, если хотите скопировать объект. Ваши варианты:

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

6
ответ дан 14 December 2019 в 08:52
поделиться

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

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

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

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

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

0
ответ дан 14 December 2019 в 08:52
поделиться

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

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

1
ответ дан 14 December 2019 в 08:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: