Статьи

Добавление Ehcache в приложение Openxava

Введение

В этой статье показано, как быстро включить Ehcache в приложениях Openxava и, таким образом, повысить производительность.

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

В конце концов, эта страница объясняет, как minuteproject относится к этому аспекту, выполняя свое обещание: ничего не писать.
В качестве примера мы возьмем витрину Lazuly.

Интеграция Openxava-Ehcache

В Openxava вы описываете свою модель в виде POJO, аннотированного Java. Аннотации исходят из стандартного ORM JPA2 и специфичных для Openxava.
Но ничто не мешает вам добавлять других. Это то, что делается для добавления кеширования. Есть также несколько конфигураций для включения кэширования.

Список действий

  1. Добавьте файл конфигурации ehcache.xml в корень ваших источников
  2. Измените файл persistence.xml, чтобы включить кэш второго уровня
  3. Добавить аннотацию кеширования (вместе с JPA2)

Замечание:

Openxava поставляется с ehcache.jar, поэтому нет необходимости добавлять зависимость.

    Подробные действия

    Добавить ehcache.xml

    В / persistence поместите файл ehcache.xml

    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    <ehcache>
        <defaultCache
                maxElementsInMemory="1000"
                eternal="false"
                timeToIdleSeconds="300"
                timeToLiveSeconds="300"
                overflowToDisk="false"
                diskPersistent="false"
                diskExpiryThreadIntervalSeconds="300"
                memoryStoreEvictionPolicy="LRU"
                />
       <cache
        name="your.domain.object"
        maxElementsInMemory="5000"
        eternal="false"
        timeToIdleSeconds="300"
        timeToLiveSeconds="600"
        overflowToDisk="false"
       />
    </ehcache>

    Изменить файл persistence.xml

    Файл Persistence.xml содержит информацию, относящуюся к единице сохранения, такую ​​как информация о пуле соединений,
    класс или конфигурация для загрузки. ‘persistence.xml’ находится в / persistence / META-INF

    Мы добавим свойства для кеша второго уровня.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <properties>
                <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
                <property name="hibernate.cache.provider_class" value="net.sf.ehcache.hibernate.SingletonEhCacheProvider" />
                <property name="net.sf.ehcache.configurationResourceName" value="/ehcache.xml" />
                <property name="hibernate.cache.use_query_cache" value="true" />
                <property name="hibernate.cache.use_second_level_cache" value="true" />
                <property name="hibernate.generate_statistics" value="true" />  
     
            </properties>

    Добавить аннотацию кеша

    Здесь вместо стандартной аннотации гибернации (Cacheable на самом деле, кажется, не работает)
    Разместите аннотацию Cache на уровне класса вашего доменного объекта.

    1
    @org.hibernate.annotations.Cache(usage = org.hibernate.annotations.CacheConcurrencyStrategy.READ_WRITE)

    пример

    Lazuly приложение

    Lazuly — это пример базы данных, содержащей информацию о конференции, которая используется для демонстрации MinuteProject.
    Minuteproject генерирует полный набор артефактов для ускорения выпуска приложения OX.
    Дополнительную информацию можно найти в витрине Minuteproject 4 Openxava Lazuly .
    В этой части мы сосредоточимся на артефактах, сгенерированных для конкретного кэширования.
    Минутный проект для генерации основывается на файле конфигурации, где мы определяем модель данных для обратного инжиниринга. В этой конфигурации есть часть обогащения, где вы можете добавить информацию.
    Одна из этих сведений касается типа содержимого, которое содержится в объекте. Есть 4 возможности (справочные данные, основные данные, псевдостатические данные, бизнес-данные в реальном времени)
    Если вы обогатите свою сущность с помощью content-type = ”master-data” или “reference-data”, MinuteProject 4 Openxava сгенерирует связанное кэширование.

    Это сделано здесь для субъекта Страна.

    1
    <entity name="COUNTRY" content-type="reference-data">

    Вот артефакты, связанные с кешем

    ehcache.xml

    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    <ehcache>
     
      <!--
        Sets the path to the directory where cache files are created.
     
        If the path is a Java System Property it is replaced by its value in the
        running VM.
     
        The following properties are translated:
        * user.home - User's home directory
        * user.dir - User's current working directory
        * java.io.tmpdir - Default temp file path
     
        Subdirectories can be specified below the property e.g. java.io.tmpdir/one
        -->
    <!--MP-MANAGED-UPDATABLE-BEGINNING-DISABLE @ehcache-main-config-conference@-->
        <diskStore path="java.io.tmpdir"/>
     
     <!--
        Mandatory Default Cache configuration. These settings will be applied to caches
        created programmtically using CacheManager.add(String cacheName)
        -->
        <defaultCache
                maxElementsInMemory="1000"
                eternal="false"
                timeToIdleSeconds="300"
                timeToLiveSeconds="300"
                overflowToDisk="false"
                diskPersistent="false"
                diskExpiryThreadIntervalSeconds="300"
                memoryStoreEvictionPolicy="LRU"
                />
    <!-- The unnamed query cache -->
       <cache
        name="org.hibernate.cache.StandardQueryCache"
        maxElementsInMemory="1000"
        eternal="false"
        timeToLiveSeconds="300"
        overflowToDisk="false"
       />
    <!--MP-MANAGED-UPDATABLE-ENDING-->
     
    <!--MP-MANAGED-UPDATABLE-BEGINNING-DISABLE @cache-entity-country-conference@-->
       <cache
        name="net.sf.mp.demo.conference.domain.admin.Country"
        maxElementsInMemory="5000"
        eternal="false"
        timeToIdleSeconds="300"
        timeToLiveSeconds="600"
        overflowToDisk="false"
       />
    <!--MP-MANAGED-UPDATABLE-ENDING-->
     
    <!--MP-MANAGED-ADDED-AREA-BEGINNING @custom-cache-definition@-->
    <!--MP-MANAGED-ADDED-AREA-ENDING @custom-cache-definition@-->
     
    </ehcache>

    persistence.xml

    01
    02
    03
    04
    05
    06
    07
    08
    09
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 version="1.0">
                  
        <!-- Tomcat + Hypersonic -->
        <persistence-unit name="default">
         <non-jta-data-source>java:comp/env/jdbc/conferenceDS</non-jta-data-source>
         <class>org.openxava.session.GalleryImage</class>
            <properties>
                <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
                <property name="hibernate.cache.provider_class" value="net.sf.ehcache.hibernate.SingletonEhCacheProvider" />
                <property name="net.sf.ehcache.configurationResourceName" value="/ehcache.xml" />
                <property name="hibernate.cache.use_query_cache" value="true" />
                <property name="hibernate.cache.use_second_level_cache" value="true" />
                <property name="hibernate.generate_statistics" value="true" />  
    <!--MP-MANAGED-ADDED-AREA-BEGINNING @properties@-->
    <!--MP-MANAGED-ADDED-AREA-ENDING @properties@-->
            </properties>
    <!--MP-MANAGED-ADDED-AREA-BEGINNING @persistence-unit@-->
    <!--MP-MANAGED-ADDED-AREA-ENDING @persistence-unit@-->
        </persistence-unit>      
     
    <!--MP-MANAGED-ADDED-AREA-BEGINNING @persistence@-->
    <!--MP-MANAGED-ADDED-AREA-ENDING @persistence@-->
     
    </persistence>

    Классовая аннотация

    1
    2
    3
    4
    5
    6
    7
    8
    9
    @org.hibernate.annotations.Cache(usage = org.hibernate.annotations.CacheConcurrencyStrategy.READ_WRITE)
    //MP-MANAGED-ADDED-AREA-BEGINNING @class-annotation@
    //MP-MANAGED-ADDED-AREA-ENDING @class-annotation@
    public class Country {
     
        @Hidden @Id @Column(name="id" )
        @GeneratedValue(strategy = GenerationType.AUTO)
        private Integer id;
    ...

    Сгенерированный код примечания

    Сгенерированный код имеет маркеры внутри комментария расширения файла.

    В MP-MANAGED-ADDED-AREA-BEGINNING и MP-MANAGED-ADDED-AREA-ENDING вы можете разместить собственный код
    В MP-MANAGED-UPDATABLE-BEGINNING-DISABLE и MP-MANAGED-UPDATABLE-ENDING вы можете изменить код. Чтобы сохранить ваши модификации, измените MP-MANAGED-UPDATABLE-BEGINNING-DISABLE на MP-MANAGED-UPDATABLE-BEGINNING-ENABLE.
    Обновляемый код предотвращает потерю настроек в течение нескольких поколений.

    Для получения дополнительной информации об обновляемом коде см. Обновляемый код Minuteproject .

    поколение

    • Поместите следующий файл mp-config-LAZULY-OPENXAVA.xml в / mywork / config
    • в командной строке выполните mp-model-generation (.sh / cmd) mp-config-LAZULY-OPENXAVA.xml
    • результирующие артефакты в / DEV / output / openxava / conference

    Для генерации используйте обновленную версию mp-config-LAZULY-OPENXAVA.xml

    001
    002
    003
    004
    005
    006
    007
    008
    009
    010
    011
    012
    013
    014
    015
    016
    017
    018
    019
    020
    021
    022
    023
    024
    025
    026
    027
    028
    029
    030
    031
    032
    033
    034
    035
    036
    037
    038
    039
    040
    041
    042
    043
    044
    045
    046
    047
    048
    049
    050
    051
    052
    053
    054
    055
    056
    057
    058
    059
    060
    061
    062
    063
    064
    065
    066
    067
    068
    069
    070
    071
    072
    073
    074
    075
    076
    077
    078
    079
    080
    081
    082
    083
    084
    085
    086
    087
    088
    089
    090
    091
    092
    093
    094
    095
    096
    097
    098
    099
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    <!DOCTYPE root>
    <generator-config>
     <configuration>
      <conventions>
       <target-convention type="enable-updatable-code-feature" />
      </conventions
      <model name="conference" version="1.0" package-root="net.sf.mp.demo">
       <data-model>
        <driver name="mysql" version="5.1.16" groupId="mysql" artifactId="mysql-connector-java"></driver>
        <dataSource>
         <driverClassName>org.gjt.mm.mysql.Driver</driverClassName>
         <url>jdbc:mysql://127.0.0.1:3306/conference</url>
         <username>root</username>
         <password>mysql</password>
        </dataSource>
        <!--
         for Oracle and DB2 please set the schema <schema> </schema>
        -->
        <primaryKeyPolicy oneGlobal="true">
         <primaryKeyPolicyPattern name="autoincrementPattern"></primaryKeyPolicyPattern>
        </primaryKeyPolicy>
       </data-model>
       <business-model>
        <!--
         <generation-condition> <condition type="exclude"
         startsWith="DUAL"></condition> </generation-condition>
        -->
        <business-package default="conference">
            <condition type="package" startsWith="STAT" result="statistics"></condition>
            <condition type="package" startsWith="COUNTRY" result="admin"></condition>
            <condition type="package" startsWith="ROLE" result="admin"></condition>   
        </business-package>
        <enrichment>
         <conventions>
          <column-naming-convention type="apply-strip-column-name-suffix"
           pattern-to-strip="_ID" />
          <reference-naming-convention
           type="apply-referenced-alias-when-no-ambiguity" is-to-plurialize="true" />
         </conventions>
     
         <entity name="COUNTRY" content-type="reference-data">
          <semantic-reference>
           <sql-path path="NAME" />
          </semantic-reference>
         </entity>
         <entity name="CONFERENCE_MEMBER">
          <semantic-reference>
           <sql-path path="FIRST_NAME" />
           <sql-path path="LAST_NAME" />
          </semantic-reference>
          <field name="STATUS">
           <property tag="checkconstraint" alias="conference_member_status">
            <property name="PENDING" value="PENDING" />
            <property name="ACTIVE" value="ACTIVE" />
           </property>
          </field>
          <field name="EMAIL">
           <stereotype stereotype="EMAIL" />
          </field>
         </entity>
         <entity name="SPEAKER">
          <field name="BIO">
           <stereotype stereotype="HTML_TEXT" />
          </field>
          <field name="PHOTO">
           <stereotype stereotype="PHOTO" />
          </field>
          <field name="WEB_SITE_URL">
           <stereotype stereotype="WEBURL" />
          </field>
         </entity>
         <entity name="PRESENTATION">
          <field name="STATUS">
           <property tag="checkconstraint" alias="presentation_status">
            <property name="PROPOSAL" value="PROPOSAL" />
            <property name="ACTIVE" value="ACTIVE" />
           </property>
          </field>
         </entity>
         <entity name="SPONSOR">
          <field name="STATUS">
           <property tag="checkconstraint" alias="sponsor_status">
            <property name="PENDING" value="PENDING" />
            <property name="ACTIVE" value="ACTIVE" />
           </property>
          </field>
          <field name="PRIVILEGE_TYPE">
           <property tag="checkconstraint" alias="sponsor_privilege">
            <property name="GOLDEN" value="Golden" />
            <property name="SILVER" value="Silver" />
            <property name="BRONZE" value="Bronze" />
           </property>
          </field>
         </entity>
         <!-- views -->
         <entity name="stat_mb_per_ctry_conf" alias="MEMBER_PER_COUNTRY_AND_CONFERENCE">
          <virtual-primary-key isRealPrimaryKey="true">
           <property name="virtualPrimaryKey" value="ID" />
          </virtual-primary-key>
         </entity>
         <entity name="stat_mb_by_role" alias="MEMBER_PER_ROLE_COUNTRY_AND_CONFERENCE">
          <virtual-primary-key isRealPrimaryKey="true">
           <property name="virtualPrimaryKey" value="id" />
          </virtual-primary-key>
          <field name="stat_mb_per_ctry_conf_ID" linkToTargetEntity="stat_mb_per_ctry_conf"
           linkToTargetField="id"></field>
         </entity>
        </enrichment>
       </business-model>
      </model>
      <targets>
       <!-- openxava -->
       <target refname="OpenXava" name="OpenXava"
        fileName="mp-template-config-openxava-last-features.xml"
        outputdir-root="../../DEV/output/openxava/conference"
        templatedir-root="../../template/framework/openxava">
       </target>
     
       <target refname="JPA2-LIB" fileName="mp-template-config-JPA2-LIB.xml"
        templatedir-root="../../template/framework/jpa">
       </target>
        
       <target refname="BSLA-LIB" fileName="mp-template-config-bsla-LIB-features.xml"
        templatedir-root="../../template/framework/bsla">
       </target>
     
       <target refname="CACHE-LIB"
          fileName="mp-template-config-CACHE-LIB.xml"
          templatedir-root="../../template/framework/cache">
       </target>
                    
      </targets>
     </configuration>
    </generator-config>

    Тест
    Чтобы убедиться, что кэширование работает правильно:

    • Включите запись в спящий режим. Добавьте следующий фрагмент в качестве дополнительных свойств в файле persistence.xml.
    1
    2
    <property name="hibernate.show_sql" value="true" />
                <property name="hibernate.format_sql" value="true" />
    • перейти к объекту, который ссылается на страну (пример адреса)
    • Когда вы просматриваете детали этой сущности, вы заметите, что существует связанная с ней сущность «страна».
    • Но во второй раз, когда вы получаете доступ к деталям этого объекта (или другого объекта, ссылающегося на тот же экземпляр страны), страна не загружается дважды из базы данных.

    Ссылка: Добавление Ehcache в приложение Openxava от нашего партнера JCG