Изучаем Java EE 7 - [101]
Рис. 6.3. Кэш второго уровня
Каждая реализация наделяется своим подходом к кэшированию объектов путем либо разработки собственного механизма, либо повторного использования уже существующих решений (с открытым исходным кодом или коммерческих). Кэширование может быть распределено по кластеру либо нет — все возможно, когда спецификация игнорирует соответствующую тему. Создатели JPA 2.0 признали, что кэш второго уровня необходим, и добавили операции кэширования в стандартный API-интерфейс. Приведенный в листинге 6.33 API-интерфейс крайне минималистичен (поскольку цель JPA не заключается в том, чтобы стандартизировать полнофункциональный кэш), однако позволяет коду выполнять запросы к некоторым сущностям и удалять их из кэша второго уровня стандартным образом. Как и менеджер сущностей, javax.persistence.Cache является интерфейсом, реализуемым системой кэширования поставщика постоянства.
>public interface Cache {
>··// Содержит ли кэш определенную сущность
>··public boolean contains(Class cls, Object id);
>··// Удаляет сущность из кэша
>··public void evict(Class cls, Object id);
>··// Удаляет сущности указанного класса (и его подклассы) из кэша
>··public void evict(Class cls);
>··// Очищает кэш
>··public void evictAll();
>··// Возвращает реализацию кэша, специфичную для поставщика
>··public
>}
Вы можете использовать этот API для проверки того, содержится ли определенная сущность в кэше второго уровня, а также для очищения всего кэша. Задействуя этот API, вы можете явным образом проинформировать поставщика постоянства о том, является ли сущность кэшируемой, с помощью аннотации @Cacheable, как показано в листинге 6.34. Если у сущности отсутствует аннотация @Cacheable, то эта сущность и ее состояние не должны кэшироваться поставщиком.
>@Entity
>@Cacheable(true)
>public class Customer {
>··@Id @GeneratedValue
>··private Long id;
>··private String firstName;
>··private String lastName;
>··private String email;
>··// Конструкторы, геттеры, сеттеры
>}
Аннотация @Cacheable принимает логическое значение. Как только вы решите, какая сущность должна быть кэшируемой, вам придется проинформировать поставщика о том, какой механизм кэширования следует использовать. Это можно сделать с помощью JPA, указав атрибут shared-cache-mode в файле persistence.xml. Далее приведены возможные значения:
• ALL — будут кэшироваться все сущности, а также связанные с ними состояния и данные;
• DISABLE_SELECTIVE — будут кэшироваться все сущности за исключением тех, что снабжены аннотацией @Cacheable(false);
• ENABLE_SELECTIVE — будут кэшироваться все сущности, снабженные аннотацией @Cacheable(true);
• NONE — кэширование будет отключено для единицы сохраняемости;
• UNSPECIFIED — поведение кэширования будет неопределенным (могут быть применены правила по умолчанию, специфичные для поставщика).
Если не задать ни одно из этих значений, то поставщик будет сам решать, какой механизм кэширования применять. В коде, приведенном в листинге 6.35, показано, как использовать соответствующий механизм кэширования. Сначала мы создаем объект Customer и обеспечиваем его постоянство. Поскольку сущность Customer является кэшируемой (см. листинг 6.34), она должна быть размещена в кэше второго уровня (с помощью метода EntityManagerFactory.getCache(). contains()). Вызов метода ache.evict(Customer.class) удаляет эту сущность из кэша.
>Customer customer = new Customer("Патриция", "Джейн", "[email protected]");
>tx.begin();
>em.persist(customer);
>tx.commit();
>// Использует EntityManagerFactory для получения Cache
>Cache cache = emf.getCache();
>// Сущность Customer должна располагаться в кэше
>assertTrue(cache.contains(Customer.class, customer.getId()));
>// Удаляет сущность Customer из кэша
>cache.evict(Customer.class);
>// Сущность Customer больше не должна располагаться в кэше
>assertFalse(cache.contains(Customer.class, customer.getId()));
Конкурентный доступ
JPA можно использовать для изменения постоянных данных, а JPQL — для извлечения данных, соответствующих определенным критериям. Все это может происходить в рамках приложения, выполняющегося в кластере с множеством узлов, множеством потоков и одной базой данных, благодаря чему осуществление конкурентного доступа к сущностям стало обычным явлением. Когда это имеет место, синхронизация должна контролироваться приложением с использованием механизма блокировки. Независимо от того, является приложение сложным или простым, есть вероятность, что вы решите применять блокировку где-нибудь в своем коде.
Чтобы проиллюстрировать проблему конкурентного доступа к базе данных, обратимся к примеру приложения с двумя конкурирующими потоками, показанными на рис. 6.4. Один поток ищет книгу по ее идентификатору и повышает цену книги на $2. Другой поток делает то же самое, но повышает цену книги на $5. Если вы выполните эти два потока одновременно в отдельных транзакциях, осуществляя манипуляции с одной и той же книгой, то не сможете предсказать окончательную цену книги. В этом примере начальная цена книги составляет $10. В зависимости от того, какая транзакция финиширует последней, цена может повыситься до $12 или 15.
Разработчику часто требуется много сторонних инструментов, чтобы создавать и поддерживать проект. Система Git — один из таких инструментов и используется для контроля промежуточных версий вашего приложения, позволяя вам исправлять ошибки, откатывать к старой версии, разрабатывать проект в команде и сливать его потом. В книге вы узнаете об основах работы с Git: установка, ключевые команды, gitHub и многое другое.В книге рассматриваются следующие темы:основы Git;ветвление в Git;Git на сервере;распределённый Git;GitHub;инструменты Git;настройка Git;Git и другие системы контроля версий.
Рассмотрено все необходимое для разработки, компиляции, отладки и запуска приложений Java. Изложены практические приемы использования как традиционных, так и новейших конструкций объектно-ориентированного языка Java, графической библиотеки классов Swing, расширенной библиотеки Java 2D, работа со звуком, печать, способы русификации программ. Приведено полное описание нововведений Java SE 7: двоичная запись чисел, строковые варианты разветвлений, "ромбовидный оператор", NIO2, новые средства многопоточности и др.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.