Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Hibernate/XML+ Ehcache. Custom keys, Как изменить генерацию ключей? 
V
    Опции темы
lamao
Дата 7.5.2012, 13:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 73
Регистрация: 23.4.2008

Репутация: нет
Всего: нет



Есть хибернейт маппинг в XML. Есть Ehcache. 
Как можно в таком варианте изменить способ генерации ключей для сущностей в кэше?
То есть, чтобы было не com.package.name.Entity#123, а скажем AAA.BBB#CCC.

Для чего это нужно. Есть два приложения (пока). Которые должны работать на одной базе. Но вполне может быть, что установлено только одно. У них есть какие-то общие данные. Но! Каждое приложение эти общие данные дополняет своими. Например есть общий com.common.User. В одном приложении у него есть список чего-то там специфического для этого приложения (com.app1.User extends com.common.User). А в другом другой список плюс еще некоторые поля (com.app2.User extends com.common.User).

Нужно настроить распределенный кэш. Пока остановились на ehcache + jgroups. Работает все вроде нормально, но эти юзеры в каждом приложении лежат в своем пакете. com.app1.User com.app2.User. Поэтому данные кэшируются под ключами com.app1.User#1 и com.app2.User#1. Соответственно т.к. ключи разные, синхронизироваться они не могут. Если переложить оба класса в пакеты с одинаковым именем, работает все на ура. Но это накладно.

Погуглив находил такое для маппинга аннотациями под спринг. Но вот под XML маппинг нету. 
PM MAIL WWW   Вверх
COVD
Дата 7.5.2012, 17:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 26.7.2005

Репутация: 4
Всего: 43



Цитата

Соответственно т.к. ключи разные, синхронизироваться они не могут

Если это разные классы, то, наверное, и правильно. 

Цитата

Если переложить оба класса в пакеты с одинаковым именем, работает все на ура.

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

При изменениях (рефакторинге) библиотеки придется останавливать все узлы, подкладывать новую версию и запускать все обратно. Это не большая проблема пока узлов всего 2.

На мой взгляд удобнее использовать только стандартные классы из JRE для описания обьектов распределенного кеша. Например, Map<String,String>. Или самостоятельно управлять значением serialVersionUID класса, если кеш использует сериализацию для обмена обьектами между узлами. В этом случае есть возможность вносить модификации без одновременного перезапуска всех узлов распределенной системы. 

Это сообщение отредактировал(а) COVD - 7.5.2012, 17:24
PM MAIL   Вверх
lamao
Дата 7.5.2012, 21:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 73
Регистрация: 23.4.2008

Репутация: нет
Всего: нет



Хм... Я вижу не совсем поняли задачу.
Есть общий класс. Он находится в общей библиотеке. Но каждое приложение расширяет этот свой класс для себя. Например админка добавляет свои поля. А собственно приложение свои. Нужно же, чтобы когда тот же юзер редактируется в админке (меняются ему права например) он удалялся и из кэша основного приложения.

Сейчас в качестве ключей используется полное имя класса+id. Нужно же эту генерацию ключей для кэша как-то кастомизировать. Для маппинга в XML. Как такое можно сделать?
PM MAIL WWW   Вверх
COVD
Дата 7.5.2012, 22:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 26.7.2005

Репутация: 4
Всего: 43




Цитата

Я вижу не совсем поняли задачу.


Зато я представляю, как работает распределенный кеш smile Мне кажется, что проблема не в ключах.
Цитата

Есть общий класс. Он находится в общей библиотеке.

И обьекты только этого класса и могут быть доступными на всех узлах кеша. Потому что класс общий. 

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

Цитата

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

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

Это сообщение отредактировал(а) COVD - 7.5.2012, 22:28
PM MAIL   Вверх
lamao
Дата 8.5.2012, 12:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 73
Регистрация: 23.4.2008

Репутация: нет
Всего: нет



Цитата

Зато я представляю, как работает распределенный кеш smile Мне кажется, что проблема не в ключах.
...............
И обьекты только этого класса и могут быть доступными на всех узлах кеша. Потому что класс общий. 

Я не специалист в кэшах, тем более распределенных. Но все же.... Для организации этого дела используется Ehcache+jgroups. Суть следующая. Каждое приложение имеет свой экземпляр кэша. То есть распределенный кэша это набор узлов, которые взаимодействуют сообщениями. И соответственно тот же юзер будет кэшироваться в каждом кэше. Если в одном приложении мы изменяем поля юзера, то нужно соответствующую запись удалить из кэша. Для этого, через jgroups всем узлам посылается сообщение

Код

2012-05-08 11:32:24,109 [DEBUG][-a775c5964-41128][net.sf.ehcache.distribution.jgroups.JGroupsCacheReceiver] - received remove:
cache=org.jtalks.EHCOMMON, key=org.jtalks.ehcommon.model.entity.User#1


Цитата

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


Примерно так
Код

public class User extends org.jtalks.common.model.entity.User {

    private Signature signature = new Signature(null);
    private int postCount;
...............


Код

public class User extends org.jtalks.common.model.entity.User {

    private static final long serialVersionUID = -6429539956660665057L;

    private List<Group> groups = new ArrayList<Group>();


Сейчас я обоих этих юзеров поместил в пакет с одним именем. Поэтому ключ для для сохранения в кэше генерируется один.
Код

org.jtalks.ehcommon.model.entity.User#1
 

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

К тому же есть еще несколько сущностей, которые необходимо иметь в распределенном кэше.
Цитата


Цитата

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

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


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

Вот такие (что не важно затерто). Показан скриншот для каждого узла.

user posted image

user posted image

Нужен способ как изменить генерацию вот этих ключей на свою. 
Еще нашел в хибернейте в классе CacheKey, который собственно и отвечает по дефолту за генерацию таких ключей, коментарий
Код

/**
     * Note that an entity name should always be the root entity
     * name, not a subclass entity name.


и дальше метод 
Код

//Mainly for OSCache
    public String toString() {
        return entityOrRoleName + '#' + key.toString();//"CacheKey#" + type.toString(key, sf);
    }

Но почему то у меня судя по всему как раз передается имя не базового класса, а именно сабклассов.


PM MAIL WWW   Вверх
COVD
Дата 8.5.2012, 17:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1655
Регистрация: 26.7.2005

Репутация: 4
Всего: 43



Цитата

Для организации этого дела используется Ehcache+jgroups. Суть следующая. Каждое приложение имеет свой экземпляр кэша. То есть распределенный кэша это набор узлов, которые взаимодействуют сообщениями. И соответственно тот же юзер будет кэшироваться в каждом кэше. Если в одном приложении мы изменяем поля юзера, то нужно соответствующую запись удалить из кэша. Для этого, через jgroups всем узлам посылается сообщение

Для меня неожиданность, что вы вручную строите распределенный кеш из двух разных фреймворков. Есть же много библиотек, где все "в одном флаконе". Например, http://www.hazelcast.com/ . Там все вопросы синхронизации внутри решаются и нет явного "посылания" сообщений через мультикаст. Но суть одна - класс обьекта общий для всех узлов. И, соответственно, единый способ генерации ключа.

У вас как я понял два приложения.
Приложение А оперирует классом User_A extends User
Приложение B оперирует классом User_B extends User 

Но в распределенный кеш можно положить только обьект User. Только тогда оба приложения могут с ним работать. А дополнительные поля наследников не передаются между узлами. Наверное, надо отказаться от наследования, сделать User member'ом классов User_A и User_B. 

С  другой стороны, у вас на самом деле не распределенный кеш, а два разных кеша, в которых хранятся обьекты разных классов, и вы ищете элегантный способ генерировать общий ключ на основании того, что эти классы - наследники User. Почему надо генерировать ключ, почему нельзя использовать уникальный userID или userEmail, которые наверняка есть в общем классе? 
PM MAIL   Вверх
lamao
Дата 10.5.2012, 10:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 73
Регистрация: 23.4.2008

Репутация: нет
Всего: нет



Решил наконец-то эту проблемму.
Еще раз уточню, в чем задача.
УЖЕ ЕСТЬ ehcache. Он уже используется для кэширования. На их же сайте есть страница Replicated Caching using JGroups, где, помими прочих вариантов, ими же опысан вариант распределенного кэша с использованием jgroups. Поэтому вариант выглядит довольно нормальным.

Цитата

У вас как я понял два приложения.
Приложение А оперирует классом User_A extends User
Приложение B оперирует классом User_B extends User 


Дальше. Да у нас именно такая ситуация. Поля и их значения совершенно не обязательно синхронизировать. Нужно лишь убедиться, что будет отображаться значения, которое в базе. То есть достатотчно просто удалять энтити из кэша, если оно где-то меняется. 

Цитата

Почему надо генерировать ключ, почему нельзя использовать уникальный userID или userEmail, которые наверняка есть в общем классе?  


Можно. Но это был вопрос топика. Как??? Хибернейт сам генерирует ключ для кэша, используя полное имя класса и его id.

Оказывается, если у нас есть иерархия (причем именно хибернейт иерархия - в маппинге), то для ключа будет использоваться имя самого общего предка в маппинге. То есть нужно замапить где-то так

Код

<class name="com.common.User">
    <subclass name="com.app1.User">
     </subclass>
</class>


Код

<class name="com.common.User">
    <subclass name="com.app2.User">
     </subclass>
</class>


Тогда имя ключа для кэша в обоих приложениях будет com.common.User#1. У нас же был маппинг без наследования (за ненадобностью). Решение, как всегда, простое.
PM MAIL WWW   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java EE (J2EE) и Spring | Следующая тема »


 




[ Время генерации скрипта: 0.0745 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.