Package cn.org.zeronote.orm.nosql

Source Code of cn.org.zeronote.orm.nosql.RedisWeakCachedCommonDao

/**
*
*/
package cn.org.zeronote.orm.nosql;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import cn.org.zeronote.orm.DataAccessException;
import cn.org.zeronote.orm.ORMTable;
import cn.org.zeronote.orm.PaginationSupport;
import cn.org.zeronote.orm.RowSelection;
import cn.org.zeronote.orm.dao.DefaultCommonDao;


/**
* 使用Rdis提供缓存支持的DAO
* @author <a href='mailto:lizheng8318@gmail.com'>lizheng</a>
*
*/
public class RedisWeakCachedCommonDao extends DefaultCommonDao {

  private static Logger logger = LoggerFactory.getLogger(RedisWeakCachedCommonDao.class);
 
  /** jedis pool */
  private JedisPool jedisPool;
 
  /** 缓存时间(单位:秒),缓存到期后自动删除,默认60秒 */
  private int cacheSeconds = 60;
  /**
   *
   */
  public RedisWeakCachedCommonDao() {
  }

  /**
   * jedis pool
   * @param jedisPool the jedisPool to set
   */
  public void setJedisPool(JedisPool jedisPool) {
    this.jedisPool = jedisPool;
  }
 
  /**
   * 缓存时间(单位:秒),缓存到期后自动删除
   * @param cacheSeconds the cacheSeconds to set
   */
  public void setCacheSeconds(int cacheSeconds) {
    this.cacheSeconds = cacheSeconds;
  }

  /**
   * 获取redis cache连接
   * @return
   */
  private Jedis getJedis() {
    Jedis jedis = null;
    try {
      jedis = jedisPool.getResource();
    } catch (Exception e) {
      logger.warn("Get redis pool error!", e);
    }
    return jedis;
  }
 
  /**
   * 生成key值
   * @param obj
   * @return
   */
  private List<String> generaCacheKey(Object obj) {
    ORMTable ormTable = obj.getClass().getAnnotation(ORMTable.class);
    if (ormTable != null) {
      String cachedTableKey = "".equalsIgnoreCase(ormTable.cachedShortAlias()) ? ormTable.tableName() : ormTable.cachedShortAlias();
      String[] cachedKeys = ormTable.cachedKey();
     
      if (cachedKeys.length > 0) {
        List<String> ks = new ArrayList<String>();
        for (int i = 0; i < cachedKeys.length; i++) {
          String cachedCol = cachedKeys[i];
          String[] fk = cachedCol.split("=");
          try {
            Field f = obj.getClass().getDeclaredField(fk[0]);
            f.setAccessible(true);
            ks.add(cachedTableKey + "." + fk[1] + "." + f.get(obj))// 表别名 + key别名 + key值
          } catch (NoSuchFieldException e) {
            logger.warn("NoSuchFieldException:{};", cachedCol, e);
            continue;
          } catch (SecurityException e) {
            logger.warn("SecurityException:{};", cachedCol, e);
            continue;
          } catch (IllegalArgumentException e) {
            logger.warn("Get field value fail:{};", cachedCol, e);
            continue;
          } catch (IllegalAccessException e) {
            logger.warn("Get field value fail:{};", cachedCol, e);
            continue;
          }
        }
        return ks;
      } else {
        return null;
      }
    } else {
      return null;
    }
  }
 
  /**
   * 清除缓存
   * @param pojos
   */
  private void deleteCache(Object... pojos) {
    Jedis jedis = getJedis();
    if (jedis != null) {
      try {
        for (Object obj : pojos) {
          List<byte[]> ks = new ArrayList<byte[]>();
         
          List<String> keys = generaCacheKey(obj);
          if (keys != null && !keys.isEmpty()) {
            for (String key : keys) {
              ks.add(key.getBytes());
            }
          }
          // 清除缓存
          jedis.del(ks.toArray(new byte[0][0]));
        }
      } finally {
        jedisPool.returnResource(jedis);
      }
    }
  }
 
  /**
   * 清除缓存
   * @param pojos
   */
  private void updateCache(Object... pojos) {
    Jedis jedis = getJedis();
    if (jedis != null) {
      try {
        for (Object obj : pojos) {
          List<String> keys = generaCacheKey(obj);
         
          if (keys != null && !keys.isEmpty()) {
            // 更新
            for (String key : keys) {
              try {
                setCache(jedis, key, obj)// key:// 表别名 + key别名 + key值
              } catch (IOException e) {
                logger.warn("Set cache value fail:{};", key, e);
                continue;
              }
            }
          }
        }
      } finally {
        jedisPool.returnResource(jedis);
      }
    }
  }
 
  /**
   * 读取缓存
   * @param jedis
   * @param key
   * @return
   * @throws IOException
   * @throws ClassNotFoundException
   */
  private Object getCache(Jedis jedis, String key) throws ClassNotFoundException, IOException {
    Object obj = null;
        if (jedis != null && jedis.isConnected()) {
          byte[] bi = jedis.get(key.getBytes());
          if (bi != null) {
          ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bi, 0, bi.length));
          obj = ois.readObject();
      }
        }
        return obj;
    }
   
    /**
     * 设置缓存对象
     * @param jedis
     * @param key
     * @param obj
     * @throws IOException
     */
    private void setCache(Jedis jedis, String key, Object obj) throws IOException {
        if (jedis != null && jedis.isConnected()) {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(obj);
            byte[] bs = bos.toByteArray();
            if (cacheSeconds > 0) {
              jedis.setex(key.getBytes(), cacheSeconds, bs);
      } else {
        jedis.set(key.getBytes(), bs);
      }
           
        }
    }

  /* (non-Javadoc)
   * @see cn.org.zeronote.orm.dao.DefaultCommonDao#updateByLogic(java.lang.Object[])
   */
  @Override
  public int updateByLogic(Object... pojos) throws DataAccessException {
    int r = super.updateByLogic(pojos);
    if (r > 0) {
      // 有更新,才清除缓存,进行同步
      deleteCache(pojos);
    }
    return r;
  }

  /* (non-Javadoc)
   * @see cn.org.zeronote.orm.dao.DefaultCommonDao#updateByPhysical(java.lang.Object[])
   */
  @Override
  public int updateByPhysical(Object... pojos) throws DataAccessException {
    int r = super.updateByPhysical(pojos);
    updateCache(pojos);
    return r;
  }

  /* (non-Javadoc)
   * @see cn.org.zeronote.orm.dao.DefaultCommonDao#deleteByLogic(java.lang.Object[])
   */
  @Override
  public int deleteByLogic(Object... pojos) throws DataAccessException {
    int r = super.deleteByLogic(pojos);
    deleteCache(pojos);
    return r;
  }

  /* (non-Javadoc)
   * @see cn.org.zeronote.orm.dao.DefaultCommonDao#deleteByPhysical(java.lang.Object[])
   */
  @Override
  public int deleteByPhysical(Object... pojos) throws DataAccessException {
    int r = super.deleteByPhysical(pojos);
    deleteCache(pojos);
    return r;
  }

  /* (non-Javadoc)
   * @see cn.org.zeronote.orm.dao.DefaultCommonDao#queryForPojoOne(java.lang.Class, java.util.Map)
   */
  @SuppressWarnings("unchecked")
  @Override
  public <T> T queryForPojoOne(Class<T> pojoType, Map<String, Object> args)
      throws DataAccessException {
    Jedis jedis = getJedis();
    if (jedis != null) {
      try {
        T t = null;
        // 先在redis里找 XXX Annotation可以cache
        ORMTable ormTable = pojoType.getAnnotation(ORMTable.class);
        String cachedTableKey = "".equalsIgnoreCase(ormTable.cachedShortAlias()) ? ormTable.tableName() : ormTable.cachedShortAlias();
       
        String[] cachedKeys = ormTable.cachedKey();
        for (String cachedKey : cachedKeys) {
          String[] ks = cachedKey.split("=");
          Object arg = args.get(ks[0]);
          if (arg != null) {
            // 存在key值,则查找,否则数据库中差
            String key = cachedTableKey + "." + ks[1] + "." + String.valueOf(arg);
            T obj = null;
            try {
              obj = (T) getCache(jedis, key);
            } catch (ClassNotFoundException e) {
              logger.warn("Get from cache fail!", e);
            } catch (IOException e) {
              logger.warn("Get from cache fail!", e);
            }
            if (obj != null) {
              t = obj;
              break;
            }
          }
        }
        // 已有,则,直接返回
        if (t != null) {
          return t;
        } else {
          // 没有再去数据库里取
          t = super.queryForPojoOne(pojoType, args);
          if (t != null) {
            // 将新获取的添加到cache里
            for (String cachedKey : cachedKeys) {
              String[] fk = cachedKey.split("=");
              try {
                Field f = t.getClass().getDeclaredField(fk[0]);
                f.setAccessible(true);
                String key = cachedTableKey + "." + fk[1] + "." + f.get(t);
                setCache(jedis, key, t);
              } catch (Exception e) {
                logger.warn("Set to cache fail!", e);
              }
            }
          }
        }
        return t;
      } finally {
        // 必须释放
        jedisPool.returnResource(jedis);
      }
    } else {
      // 没有redis缓存,直接从数据库中获取
      return super.queryForPojoOne(pojoType, args);
    }
   
  }

  /* (non-Javadoc)
   * @see cn.org.zeronote.orm.dao.DefaultCommonDao#queryForPojoList(java.lang.Class, java.lang.String, java.lang.Object[])
   */
  @Override
  public <T> List<T> queryForPojoList(Class<T> pojoType, String col,
      Object[] args, String... requireFields) throws DataAccessException {
    // TODO
    // 先从缓存里查
    // 缓存里没有的再从数据库里查
    // 拼装到一起
    // 按照输入顺序排序
    return super.queryForPojoList(pojoType, col, args);
  }

  /* (non-Javadoc)
   * @see cn.org.zeronote.orm.dao.DefaultCommonDao#queryForPaginatedPojoList(java.lang.Class, java.util.Map, cn.org.zeronote.orm.RowSelection)
   */
  @Override
  public <T> PaginationSupport<T> queryForPaginatedPojoList(
      Class<T> pojoType, Map<String, Object> args,
      RowSelection rowSelection) throws DataAccessException {
    // TODO Auto-generated method stub
    return super.queryForPaginatedPojoList(pojoType, args, rowSelection);
  }
 
}
TOP

Related Classes of cn.org.zeronote.orm.nosql.RedisWeakCachedCommonDao

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.