读书人

hibernate 2快取 + cluster

发布时间: 2012-07-22 19:31:15 作者: rapoo

hibernate 二快取 + cluster

原文出自:http://mmmmtodd.blogspot.com/2012/03/hibernate-cluster.html

?

result as below
我相同 ? true  我是一快取

果示 : from 良格葛 -- 第二次查料,在快取中找到料物件,於是直接返回,第一次查到的料物件是同一例,所以示 true 的果。

那要怎快取清掉呢?
可以透evict()某物件快取中移去,或使用clear()清除快取中的所有物件,
例如 :
public String firstCache() {    Users userA = usersService.getById(1L);    // session.clear() || session.evict(userA);    Users userB = usersService.getById(1L);    System.out.println("我相同 ? " + (userA == userB));        System.out.println("我是一快取");    return SUCCESS;  }

答案就成 false
我相同 ? false  我是一快取


小:取的料很大,每一次 request 就去取一次,造成相的,所以有了二快取西。
就是料有修改,不管次,只要有定二快取,session 就算了以後,二快取如果有的,也不 DB select。


以下始介二快取:

首先,先看一下程式片段:
public String noCache() {    Users uA = usersService.getByAccount("markyeh");    System.out.println("我有 快取 : " + uA.getUpdateTime());    return SUCCESS;  }
然後我了次 http://localhost:8080/Cache/noCache.do

result as below:
Hibernate:     /* FROM    Users WHERE    account = ? */ select        users0_.id as id0_,        users0_.account as account0_,        users0_.address as address0_,        users0_.area1 as area4_0_,        users0_.area2 as area5_0_,        users0_.create_time as create6_0_,        users0_.email as email0_,        users0_.icon as icon0_,        users0_.mobile as mobile0_,        users0_.name as name0_,        users0_.password as password0_,        users0_.reg_ip as reg12_0_,        users0_.reg_random_code as reg13_0_,        users0_.roc_id as roc14_0_,        users0_.score as score0_,        users0_.state as state0_,        users0_.update_time as update17_0_     from        users users0_     where        users0_.account=?我有 快取 : 2012-03-15 10:37:41.395Hibernate:     /* FROM    Users WHERE    account = ? */ select        users0_.id as id0_,        users0_.account as account0_,        users0_.address as address0_,        users0_.area1 as area4_0_,        users0_.area2 as area5_0_,        users0_.create_time as create6_0_,        users0_.email as email0_,        users0_.icon as icon0_,        users0_.mobile as mobile0_,        users0_.name as name0_,        users0_.password as password0_,        users0_.reg_ip as reg12_0_,        users0_.reg_random_code as reg13_0_,        users0_.roc_id as roc14_0_,        users0_.score as score0_,        users0_.state as state0_,        users0_.update_time as update17_0_     from        users users0_     where        users0_.account=?我有 快取 : 2012-03-15 10:37:41.395
行果:hibernate db 行了次的 select,但明明相同的西,怎做才能只 db select 一次就好呢?


就始明如何定 hibernate 的二快取:
我的境如下
struts2 + hibernate + spring + ehcache(第三方作 cache 的套件)


1. 在 spring 定中,在 hibernate 注入的 bean ,增加二快取的定
<bean id="sessionFactory"    ref="ihergoSqlDataSource" />    <property name="hibernateProperties">      <props>        <!--         <prop key="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</prop>        -->        <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>        <prop key="hibernate.connection.characterEncoding">utf-8</prop>        <prop key="hibernate.show_sql">true</prop>        <prop key="hibernate.format_sql">true</prop>        <prop key="hibernate.use_sql_comments">true</prop>        <prop key="hibernate.cache.use_second_level_cache">true</prop> <!-- 要不要使用二快取 -->        <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop> <!-- 指定 EHCache -->        <prop key="hibernate.cache.region.factory_class">net.sf.ehcache.hibernate.SingletonEhCacheRegionFactory</prop>         <prop key="hibernate.cache.use_query_cache">true</prop> <!-- query 也要快取-->        <prop key="hibernate.hbm2ddl.auto">update</prop>      </props>    </property>    <property name="packagesToScan">      <list>        <value>mt.buyer.db.entity</value>      </list>    </property>  </bean>
2. 定 entity (以 annotation 例)
@Entity@Cache(usage = CacheConcurrencyStrategy.READ_WRITE) // <---, 只定 read_write@Table(name = "users")public class Users implements Serializable {  @Id  @GeneratedValue(strategy = GenerationType.AUTO)  private long id;  /**   *    */  @Column(name = "account", length = 20, nullable = false)  private String account;  ...}
3. dao
// 快取  public Users getByAccountUserCache(final String account) {    final String hql = "FROM Users WHERE account = :account ";        List memberList = getHibernateTemplate().executeFind(        new HibernateCallback>() {          public List doInHibernate(Session hbmSs)              throws HibernateException, SQLException {            // TODO Auto-generated method stub            Query query = hbmSs.createQuery(hql);            query.setString("account", account);            query.setCacheable(true); // <----             return query.list();          }        });    if (memberList != null && memberList.size() > 0) {      return (Users) memberList.get(0);    }    return null;  }  // 有快取  public Users getByAccount(String account) {    final String hql = "FROM Users WHERE account = ?";    List memberList = getHibernateTemplate().find(hql, account);    if (memberList != null && memberList.size() > 0) {      return (Users) memberList.get(0);    }    return null;  }
4. 增加定 ehcache.xml 放在 src 下(取入, 也可用 spring 注入)
<?xml version="1.0" encoding="UTF-8"?><ehcache><diskStore path="java.io.tmpdir" /><defaultCache maxElementsInMemory="10000" eternal="false"overflowToDisk="true" timeToIdleSeconds="300" timeToLiveSeconds="180"diskPersistent="false" diskExpiryThreadIntervalSeconds="120" /><!-- Hibernate --><cache name="org.hibernate.cache.StandardQueryCache"maxElementsInMemory="5" eternal="false" timeToLiveSeconds="120"overflowToDisk="true"></cache><cache name="org.hibernate.cache.UpdateTimestampsCache"maxElementsInMemory="5000" eternal="true" overflowToDisk="true"></cache></ehcache>
5. 程式 (action)
public String cache() {    Users uA = usersService.getByAccountUserCache("markyeh");    Users uB = usersService.getByAccountUserCache("markyeh");    System.out.println("快取 : " + uA.getUpdateTime());    System.out.println("快取 : " + uB.getUpdateTime());    return SUCCESS;  }
6. 行 : http://localhost:8080/Cache/cache.do
Hibernate:     /* FROM    Users WHERE    account = :account  */ select        users0_.id as id0_,        users0_.account as account0_,        users0_.address as address0_,        users0_.area1 as area4_0_,        users0_.area2 as area5_0_,        users0_.create_time as create6_0_,        users0_.email as email0_,        users0_.icon as icon0_,        users0_.mobile as mobile0_,        users0_.name as name0_,        users0_.password as password0_,        users0_.reg_ip as reg12_0_,        users0_.reg_random_code as reg13_0_,        users0_.roc_id as roc14_0_,        users0_.score as score0_,        users0_.state as state0_,        users0_.update_time as update17_0_     from        users users0_     where        users0_.account=?快取 : 2012-03-15 10:37:41.395快取 : 2012-03-15 10:37:41.395
7. 可以, 第二次的查就已有再 db search 了, 如果再行相同一次(也就是再一 request 到後台)
快取 : 2012-03-15 10:37:41.395快取 : 2012-03-15 10:37:41.395
可以看到,都是二快取的地方取得料,,大家,那修改怎判要不要取得新料 8. 我加入下面的程式:
public String update() {    // Users u = usersService.getByAccountUserCache("markyeh");    Users u = usersService.getByAccount("markyeh");    u.setArea1(3);    u.setUpdateTime(new Date());    usersService.update(u);    System.out.println("我修改了 : " + u.getUpdateTime());        return SUCCESS;  }
9. 分依序行 3 a) http://localhost:8080/Cache/cache.do b) http://localhost:8080/Cache/update.do c) http://localhost:8080/Cache/cache.do
// a) selectHibernate:     /* FROM    Users WHERE    account = :account  */ select        users0_.id as id0_,        users0_.account as account0_,        users0_.address as address0_,        users0_.area1 as area4_0_,        users0_.area2 as area5_0_,        users0_.create_time as create6_0_,        users0_.email as email0_,        users0_.icon as icon0_,        users0_.mobile as mobile0_,        users0_.name as name0_,        users0_.password as password0_,        users0_.reg_ip as reg12_0_,        users0_.reg_random_code as reg13_0_,        users0_.roc_id as roc14_0_,        users0_.score as score0_,        users0_.state as state0_,        users0_.update_time as update17_0_     from        users users0_     where        users0_.account=?快取 : 2012-03-15 16:39:16.944快取 : 2012-03-15 16:39:16.944第一次行, 果一, 不次// b) updateHibernate:     /* FROM    Users WHERE    account = ? */ select        users0_.id as id0_,        users0_.account as account0_,        users0_.address as address0_,        users0_.area1 as area4_0_,        users0_.area2 as area5_0_,        users0_.create_time as create6_0_,        users0_.email as email0_,        users0_.icon as icon0_,        users0_.mobile as mobile0_,        users0_.name as name0_,        users0_.password as password0_,        users0_.reg_ip as reg12_0_,        users0_.reg_random_code as reg13_0_,        users0_.roc_id as roc14_0_,        users0_.score as score0_,        users0_.state as state0_,        users0_.update_time as update17_0_     from        users users0_     where        users0_.account=?Hibernate:     /* update        mt.buyer.db.entity.Users */ update            users         set            account=?,            address=?,            area1=?,            area2=?,            create_time=?,            email=?,            icon=?,            mobile=?,            name=?,            password=?,            reg_ip=?,            reg_random_code=?,            roc_id=?,            score=?,            state=?,            update_time=?         where            id=?我修改了 : Thu Mar 15 16:40:19 CST 2012// c) selectHibernate:     /* FROM    Users WHERE    account = :account  */ select        users0_.id as id0_,        users0_.account as account0_,        users0_.address as address0_,        users0_.area1 as area4_0_,        users0_.area2 as area5_0_,        users0_.create_time as create6_0_,        users0_.email as email0_,        users0_.icon as icon0_,        users0_.mobile as mobile0_,        users0_.name as name0_,        users0_.password as password0_,        users0_.reg_ip as reg12_0_,        users0_.reg_random_code as reg13_0_,        users0_.roc_id as roc14_0_,        users0_.score as score0_,        users0_.state as state0_,        users0_.update_time as update17_0_     from        users users0_     where        users0_.account=?快取 : 2012-03-15 16:40:19.524快取 : 2012-03-15 16:40:19.524
可以,ehcache 自判 cache 的西跟 db 的是不是不一了,如果不一再 select 一次放入二快取


小: ehcache.xml 可以定的方式很多,只是 demo,而我也在,官方表示可以做到 tx 的管理,所以是去看一下文件比好。

考文件:

http://www.ehcache.org/documentation/user-guide/hibernate

http://renren.it/a/JAVAbiancheng/Spring/20101022/55282.html

http://caterpillar.onlyfun.net/Gossip/HibernateGossip/SecondLevelCache.html





,因公司架 tomcat cluster ,那...二快取有法共用? 答案是可以的


以下介 cluster 境下怎共用二快取的料:

考了官方文件後,必加入第三方的套件 terracotta 先看看官方的明:

http://terracotta.org/documentation/enterprise-ehcache/get-started

其套件就是一 server ,由 server 你控管各 session

而我的流程大概如下

1. 先 2 tomcat,分定 port 8080, 8081

2. 加入相 jar

3. 修改 ehcache.xml

4. depoly 程式

5. terracotta server run 起

6.



就第二始:

2. ehcache 官有,要做到For Terracotta clustering, download a full Ehcache distribution. 所以先下好案,解,容
hibernate 2快取 + cluster相的 lib 加入 ap : ehcache-terracotta-2.5.1.jar terracotta-toolkit-1.4-runtime-4.1.0.jar ... 3.
<?xml version="1.0" encoding="UTF-8"?><ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true"monitoring="autodetect"><terracottaConfig url="localhost:9510" /> <!-- 接到 terracotta server 的 ip  port --><defaultCache maxElementsInMemory="10000" eternal="false"overflowToDisk="false" timeToIdleSeconds="300" timeToLiveSeconds="180"diskPersistent="false" diskExpiryThreadIntervalSeconds="120" /> <!-- diskPersistent 必成 false --><!-- Hibernate --><cache name="org.hibernate.cache.StandardQueryCache"maxElementsInMemory="5" eternal="false" timeToLiveSeconds="120"overflowToDisk="false"> <!-- overflowToDisk 必成 false --><terracotta /></cache><cache name="org.hibernate.cache.UpdateTimestampsCache"maxElementsInMemory="5000" eternal="true" overflowToDisk="false"> <!-- overflowToDisk 必成 false --><terracotta /></cache></ehcache>
5. 在那料, 找到 \ehcache-2.5.1\terracotta\bin\start-tc-server.bat 行, server run 起
hibernate 2快取 + cluster6. : 分行 a) http://localhost:8080/Cache/cache.do b) http://localhost:8081/Cache/cache.do 成功...就不了 提供程式下的 https://www.asuswebstorage.com/navigate/share/GYYVXWYN7Y
...
充 :

分散式 cache 考
http://www.informit.com/guides/content.aspx?g=java&seqNum=630
http://bbs.51osos.com/thread-4570-1-1.html
http://terracotta.org/documentation/enterprise-ehcache/configuration-guide

然後多西都有, 如: terracotta 也可以加入 xml 定, 定 port, 而且 terracotta 本身也可以做 cluster
反正看一下官就了

读书人网 >开源软件

热点推荐