Sto lavorando a un'applicazione utilizzando Spring Data JPA con Hibernate e sto tentando di abilitare la cache di secondo livello utilizzando ehcache. Ho rotto la mia applicazione in due progetti:Dati primari JPA con Hibernate ed Ehcache non funzionanti
- CoreDataFacade: dove mi definisco operazioni di accesso ai dati utilizzando QueryDSL, Primavera dati JPA con Hibernate e EHCache.
- QueryComponent: è un progetto di avvio a molla che utilizza il progetto CoreDataFacade per accedere ai dati.
configurazione di CoreDataFacade è la seguente:
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.7.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.6.Final</version>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>2.4.7</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
<version>4.3.6.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.3.6.Final</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.33</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency>
<dependency>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<version>3.6.0</version>
</dependency>
<dependency>
<groupId>com.mysema.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
<version>3.6.0</version>
</dependency>
applicazione context.xml
annotazioni<jpa:repositories
base-package="com.coredata.services.impl.sql.mysql.repositories" />
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close" p:driverClass="com.mysql.jdbc.Driver"
p:jdbcUrl="jdbc:mysql://localhost/FOO" p:user="****" p:password="****"
p:acquireIncrement="5" p:minPoolSize="10" p:maxPoolSize="100"
p:maxIdleTime="1200" p:unreturnedConnectionTimeout="120" />
<bean id="jpaVendorAdapter"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
p:database="MYSQL" p:showSql="true" p:generateDdl="true" />
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
p:dataSource-ref="dataSource" p:jpaVendorAdapter-ref="jpaVendorAdapter"
p:packagesToScan="com.coredata.services.impl.sql.mysql.model">
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory
</prop>
<prop key="javax.persistence.sharedCache.mode">ENABLE_SELECTIVE</prop>
<prop key="hibernate.generate_statistics">true</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" />
Entity cache
@Entity
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY, region="cache_states")
@Table(name="states")
public class State implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="id_state")
private int idState;
...
ehcache.xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
<defaultCache maxElementsInMemory="10000" eternal="false"
timeToIdleSeconds="120" timeToLiveSeconds="120"
overflowToDisk="false" diskPersistent="false" />
<cache name="cache_states" maxElementsInMemory="300" eternal="false"
timeToIdleSeconds="5000" timeToLiveSeconds="5000" overflowToDisk="false">
</cache>
</ehcache>
importazioni di configurazione di QueryComponent sopra la configurazione ed escludere JPA:
@Configuration
@PropertySource("classpath:/component.properties")
@ImportResource({ "classpath:/application-context.xml"})
@EnableAutoConfiguration(exclude = { JpaRepositoriesAutoConfiguration.class })
public class Application {
public void run(String... args) { }
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Quando ComponentQuery inizia tutto è OK. Quando eseguire una query per trovare tutti gli stati in banca dati, ibernazione statistiche sono i seguenti:
Hibernate: select count(state0_.id_state) as col_0_0_ from states state0_
Hibernate: select state0_.id_state as id_stat1_5_, state0_.name_state as name_e2_5_ from states state0_ limit ?
[2015-08-31 18:52:21.402] boot - 1946 INFO [SimpleAsyncTaskExecutor-1] --- StatisticalLoggingSessionEventListener: Session Metrics {
32992 nanoseconds spent acquiring 1 JDBC connections;
0 nanoseconds spent releasing 0 JDBC connections;
238285 nanoseconds spent preparing 2 JDBC statements;
935976 nanoseconds spent executing 2 JDBC statements;
0 nanoseconds spent executing 0 JDBC batches;
269717 nanoseconds spent performing 4 L2C puts;
0 nanoseconds spent performing 0 L2C hits;
0 nanoseconds spent performing 0 L2C misses;
0 nanoseconds spent executing 0 flushes (flushing a total of 0 entities and 0 collections);
68790 nanoseconds spent executing 2 partial-flushes (flushing a total of 0 entities and 0 collections)
}
Quando mi ripeto la stessa query ho avuto questa statistica:
Hibernate: select count(state0_.id_state) as col_0_0_ from states state0_
Hibernate: select state0_.id_state as id_stat1_5_, state0_.name_state as name_e2_5_ from states state0_ limit ?
[2015-08-31 19:26:48.479] boot - 1946 INFO [SimpleAsyncTaskExecutor-1] --- StatisticalLoggingSessionEventListener: Session Metrics {
314930 nanoseconds spent acquiring 1 JDBC connections;
0 nanoseconds spent releasing 0 JDBC connections;
356832 nanoseconds spent preparing 2 JDBC statements;
681615 nanoseconds spent executing 2 JDBC statements;
0 nanoseconds spent executing 0 JDBC batches;
209324 nanoseconds spent performing 4 L2C puts;
0 nanoseconds spent performing 0 L2C hits;
0 nanoseconds spent performing 0 L2C misses;
0 nanoseconds spent executing 0 flushes (flushing a total of 0 entities and 0 collections);
12368 nanoseconds spent executing 2 partial-flushes (flushing a total of 0 entities and 0 collections)
}
Sembra che ogni query sta mettendo risultati (4 membri nel database) nella cache:
269717 nanoseconds spent performing 4 L2C puts;
209324 nanoseconds spent performing 4 L2C puts;
mi aspetto seconda query per retrive i dati dalla cache ma vale statistiche pro e contro sono pari a zero:
0 nanoseconds spent performing 0 L2C hits;
0 nanoseconds spent performing 0 L2C misses;
La mia domanda è: perché i riscontri L2C e quelli L2C sono zero quando eseguo la seconda query?
UPDATE
Ecco come sto correndo la mia ricerca
Reposiory
sto lavorando con QueryDSL con JPA dati primaverili.Ho seguito questo tutorial di integrare il mio JpaRepository utilizzando QueryDslPredicateExecutor
public interface StateRepository extends JpaRepository<State, Integer>, QueryDslPredicateExecutor<State> {
}
Servizio
Nel mio servizio eseguo la mia query utilizzando queryDLS predicati e PathBuilder come mostrato in questo grande article in modo che, posso trovare Uniti o qualsiasi altra entità da qualsiasi campo. E.g "StateName = Texas", "StatePopulation = 26448193".
@Autowired
StateRepository repo;
public List<State> getStatesByFields(String options, Integer page, Integer pageSize,String order) {
PredicateBuilder predicateBuilder = new PredicateBuilder().onEntity("State")
Pattern pattern = Pattern.compile(OPERATION_PATTERN);
Matcher matcher = pattern.matcher(options + ",");
while (matcher.find()) {
predicateBuilder.with(matcher.group(1), matcher.group(2), matcher.group(3));
}
PageRequest pag = new PageRequest(page, page_size)
BooleanExpression predicate = predicateBuilder.build();
//findAll is provided by QueryDslPredicateExecutor interface
Page<State> result = repo.findAll(predicate, pag);
}
Le query vengono eseguite come un incantesimo, ma i dati non sembrano essere memorizzati nella cache.
Aggiungere le query in esecuzione. – manish
possibile duplicato di [Inefficienti prestazioni EhCache] (http://stackoverflow.com/questions/27334492/inefficient-ehcache-performance) –
@manish, ho aggiornato la mia domanda con le informazioni sulle query. –