Maven 3 + Hibernate 4 + Spring 3 + Ehcache + Spring Cache

时间:2022-08-17 05:19:34

介绍

这是一个集成二级缓存(确切的说是ehcache)和spring3以及hibernate4.1的一个快速指导

下边是所使用的api的版本和框架的版本

Java 1.6

Spring 3.2.8.RELEASE

Hibernate 4.2.11.FINAL

Mysql 5

JUnit 4.11

警告:使用Java 8会导致 “org.springframework.core.NestedIOException: ASM ClassReader failed to parse class file – probably due to a new Java class file version that isn’t supported yet …”

警告:使用hibernate4.3.x会导致 “ERROR SessionFactoryImpl:1518 – HHH000302: Unable to construct current session context [org.springframework.orm.hibernate4.SpringSessionContext]java.lang.reflect.InvocationTargetException”

在这个指导里边你将会看到:

使用spring和junit进行测试,以及application加载

dao和service分层

使用ehcache作为二级缓存

spring缓存

spring3+hibernate4+ehcache集成

hibernate统计

many-to-many映射关系

DB表

这个不需要担心,表会自动创建
CREATE DATABASE `learn`
    CHARACTER SET 'utf8'
    COLLATE 'utf8_general_ci';
 
USE `learn`;

项目结构

Maven 3 + Hibernate 4 + Spring 3 + Ehcache + Spring Cache

依赖(pom.xml)

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>info.hevi.learn</groupId>
    <artifactId>spring-hibernate-ehcache</artifactId>
    <version>1.0</version>
 
    <description>Annotation Based Spring 3 + Hibernate 4 + EHCache + log4j Demo</description>
 
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.build.mainClass>info.hevi.learn.spring3hibernate4ehcache.Main</project.build.mainClass>
        <java.version>1.6</java.version>
        <spring.version>3.2.8.RELEASE</spring.version>
        <hibernate.version>4.2.11.Final</hibernate.version>
 
    </properties>
 
    <dependencies>
 
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
 
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${spring.version}</version>
        </dependency>
 
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!--@Transactional -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${spring.version}</version>
        </dependency>
 
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
 
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-ehcache</artifactId>
            <version>${hibernate.version}</version>
        </dependency>
 
        <!-- connection pooling with c3p0 -->
        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.1.2</version>
        </dependency>
 
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>    
 
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.27</version>
        </dependency>
 
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
 
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.1</version>
        </dependency>
 
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
            <scope>test</scope>
 
        </dependency>
 
    </dependencies>
 
    <repositories>
 
        <repository>
            <id>JBoss repository</id>
            <url>http://repository.jboss.org/nexus/content/groups/public/</url>
        </repository>
 
        <repository>
            <id>java.net-Public</id>
            <url>https://maven.java.net/content/groups/public/</url>
        </repository>
 
    </repositories>
 
</project>

Bean以及hibernate定义(applicationContext.xml)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans-3.2.xsd  http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context-3.2.xsd  http://www.springframework.org/schema/tx  http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
 
    <!-- Autowired -->
    <!--  used to activate annotations in beans already registered in the application context (no matter if they were defined with XML or by package scanning) -->
    <context:annotation-config/>
    <!-- scans packages to find and register beans within the application context. -->
    <context:component-scan base-package="info.hevi.learn.spring3hibernate4ehcache"/>
 
    <!-- enable @Transactional Annotation -->
    <tx:annotation-driven transaction-manager="transactionManager"/>
 
    <!--spring cache-->
    <bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
        <property name="caches">
            <set>
                <bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="task" />
            </set>
        </property>
    </bean>
 
    <!-- @PersistenceUnit annotation -->
    <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
 
    <!--  classpath*:*.properties-->
    <context:property-placeholder location="classpath:db.properties"/>
 
    <!-- data source with c3p0 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"
          p:driverClass="${jdbc.driverClassName}"
          p:jdbcUrl="${jdbc.url}"
          p:user="${jdbc.username}"
          p:password="${jdbc.password}"
          p:acquireIncrement="${c3p0.acquire_increment}"
          p:minPoolSize="${c3p0.min_size}"
          p:maxPoolSize="${c3p0.max_size}"
          p:maxIdleTime="${c3p0.max_idle_time}"
          p:unreturnedConnectionTimeout="${c3p0.unreturned_connection_timeout}"/>
 
    <!-- Hibernate as JPA vendor-->
    <bean id="jpaAdapter"
          class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"
          p:database="${jpa.database}" p:showSql="${jpa.showSql}"/>
 
    <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
 
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                <!--<prop key="hibernate.connection.autocommit">${hibernate.connection.autocommit}</prop>-->
 
                <prop key="hibernate.cache.use_second_level_cache">true</prop>
                <prop key="hibernate.cache.use_query_cache">true</prop>
                <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>
                <prop key="hibernate.show_sql">true</prop>
 
                <!--useful for debugging-->
                <prop key="hibernate.generate_statistics">true</prop>
            </props>
        </property>
        <property name="packagesToScan" value="info.hevi.learn.spring3hibernate4ehcache"/>
    </bean>
 
    <bean id="transactionManager"
          class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>
</beans>

Ehcache cache definitions (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"
         updateCheck="false">
    <diskStore path="cacheIO" />
 
    <defaultCache maxElementsInMemory="10000" eternal="true"
                  overflowToDisk="false" diskPersistent="false"
                  diskExpiryThreadIntervalSeconds="1800" memoryStoreEvictionPolicy="FIFO">
    </defaultCache>
 
    <cache name="info.hevi.learn.spring3hibernate4ehcache.domain.Country"
           maxElementsInMemory="300"
           eternal="true"
           overflowToDisk="false"
           timeToIdleSeconds="12000"
           timeToLiveSeconds="12000"
           diskPersistent="false"
           diskExpiryThreadIntervalSeconds="120"
           memoryStoreEvictionPolicy="LRU"  />
 
    <cache name="countryCache"
           maxElementsInMemory="300"
           eternal="true"
           overflowToDisk="false"
           timeToIdleSeconds="12000"
           timeToLiveSeconds="12000"
           diskPersistent="false"
           diskExpiryThreadIntervalSeconds="120"
           memoryStoreEvictionPolicy="LRU"  />
 
    <cache name="countryByNameCache"
           maxElementsInMemory="300"
           eternal="true"
           overflowToDisk="false"
           timeToIdleSeconds="12000"
           timeToLiveSeconds="12000"
           diskPersistent="false"
           diskExpiryThreadIntervalSeconds="120"
           memoryStoreEvictionPolicy="LRU"  />
 
</ehcache>

类图

Maven 3 + Hibernate 4 + Spring 3 + Ehcache + Spring Cache

测试文件

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"/applicationContext.xml"})
public class MainTest {
 
    @Autowired
    ILanguageService languageService;
 
    @Autowired
    ICountryService countryService;
 
    @After
    public void cleanup() {
        Logger rootLogger = Logger.getRootLogger();
        rootLogger.setLevel(Level.ERROR);
 
        countryService.deleteAll();
        languageService.deleteAll();
    }
 
    @Before
    public void setup() {
        Logger rootLogger = Logger.getRootLogger();
        Level level = rootLogger.getLevel();
        rootLogger.setLevel(Level.ERROR);
 
        Language english = new Language("english");
        Language french = new Language("french");
        Language german = new Language("german");
        Language spanish = new Language("spanish");
        Language turkish = new Language("turkish");
        Language finnish = new Language("finnish");
 
        languageService.save(english);
        languageService.save(french);
        languageService.save(german);
        languageService.save(spanish);
        languageService.save(turkish);
        languageService.save(finnish);
 
        Country uk = new Country("uk");
        Country us = new Country("us");
        Country tr = new Country("tr");
        Country es = new Country("es");
        Country sw = new Country("sw");
        Country fn = new Country("fn");
        Country gr = new Country("gr");
 
        countryService.save(uk);
        countryService.save(us);
        countryService.save(tr);
        countryService.save(es);
        countryService.save(fn);
        countryService.save(sw);
        countryService.save(gr);
 
        Country country = countryService.getByName("gr");
 
        // adding some languages to Greece
        country.getLanguages().add(english);
        country.getLanguages().add(finnish);
        country.getLanguages().add(french);
        country.getLanguages().add(turkish);
        countryService.save(country);
        rootLogger.setLevel(level);
    }
 
    @Test
    public void testCache() {
        countryService.getAll();
        countryService.getByName("gr");
        countryService.getAll();
    }
}

源码下载