这个是类定义,都是POJO类,纯数据
以下代码将POJO类反射到REDIS中,采用JSON序列化类数据。
public static <T> T save(T model, String indexName) throws Exception { String modelName = model.getClass().getSimpleName(); Jedis jedis = jPool().getResource(); Long id = null; try { id = (Long) PropertyUtils.getSimpleProperty(model, "id"); if (null == id) { // Key = "User:id" id = getModelIdValueNext(jedis, modelName); //TODO: Will must check this id data is not exists PropertyUtils.setSimpleProperty(model, "id", id); //insert id to all list, we can list all id's for get all jedis.sadd(modelName+":all", id.toString()); } //convert object to json string String valueJson = PojoMapper.toJson(model, false); //save data to redis jedis.set(modelName+":"+id, valueJson); //check if index if(null != indexName) { //Key: User:name mapKey:hujianjun@baolemon.com mapValue:1002, will use name value to index id Object indexValue = PropertyUtils.getSimpleProperty(model, indexName); if (null != indexValue) jedis.hset(modelName+":"+indexName, indexValue.toString(), id.toString()); } //notify Database to update this change to DB appendToUpdateList(jedis, model.getClass(), "U", id); } catch (Exception e) { e.printStackTrace(); throw e; } finally { jPool().returnResource(jedis); } return model; }
以下代码将数据从Redis中读取出来,再反射写入到DB(后台线程做)
1、读取数据,并调用jdbc来写入
public class DbWriterTimerTask extends TimerTask { private static final Logger LOG = LoggerFactory.getLogger(DbWriterTimerTask.class); public static boolean isRunning = false; @Override public void run() { if (!isRunning) { isRunning = true; Date begin = new Date(); LOG.info("DbWriterTimerTask begin at {} ...", begin); executeTask(); isRunning = false; Date end = new Date(); LOG.info("DbWriterTimerTask finish at {}, till for {} millseconds.", end, (end.getTime() -begin.getTime())); } else { LOG.error("DbWriterTimerTask is executing now ..."); } } public void executeTask() { int total=0; int inserted=0; int updated=0; int duplicated=0; int errored=0; Set<String> setModels = new HashSet<String>(); try { //Thread.sleep(3000); long doCount = Configure.getPropertyLong("dbWriter.docount", 20); int timeExpire = Configure.getPropertyInt("dbWriter.timeexpire", 60*60); List<DbUpdateItem> list = RedisDAO.retrieveUpdateList(doCount); if(list==null) return; total = list.size(); while (list.size() > 0) { DbUpdateItem item = list.remove(0); try { //save ids firstly if(!setModels.contains(item.m)) { if(writeBackIdValueFromModel(item.m)) setModels.add(item.m); } //find item from redis //找到class的类定义 Class<?> clazz = MySqlDAO.simpleDb().getClassByName(item.m); //从Redis加载类实体数据,不同的对象,加载方式会不同,因为有些对象是类自己控制序列化 Object object=null; if(clazz.getSimpleName().equals("CharaValues")) { object = CharaValues.find(item.id); }else if(clazz.getSimpleName().equals("CharaBox")) { object = CharaBox.find(item.id); }else if(clazz.getSimpleName().equals("CharaTask")) { object = CharaTask.find(item.id); } else { object = RedisDAO.find(clazz, item.id); } //save to db if(object==null) { LOG.error("can not find {} with {}.", item.m, item.id); errored++; } else { //find it in db Object o = MySqlDAO.simpleDb().getById(clazz, item.id); if(o==null) { MySqlDAO.simpleDb().create(object); inserted++; }else { MySqlDAO.simpleDb().updateEntity(object); updated++; } } //设置过期标志 RedisDAO.expireObject(item.m, item.id.longValue(), timeExpire); } catch(Exception e) { LOG.error("writeDb error.", e); } finally { //find all same object and pop it Iterator<DbUpdateItem> iter = list.iterator(); while(iter.hasNext()) { DbUpdateItem it = iter.next(); //if(it.m.equals(item.m) && it.o.equals(item.o) && it.id.equals(item.id)) { if(it.m.equals(item.m) && it.id.equals(item.id)) { iter.remove(); //pop it duplicated++; } } } } LOG.info("Total {} been processed, Inserted {} records, Updated {} records, skip duplicated {} records, errrors {} records.", total, inserted, updated, duplicated, errored); } catch(Exception e) { LOG.error("executeTask error.", e); } return ; } public boolean writeBackIdValueFromModel(String modelName) { boolean result = false; Jedis jedis = RedisDAO.getResource(); try { String idString = jedis.get(modelName+":id"); if(idString==null) return true; Long idValue = Long.parseLong(idString); result = writeBackIdValue(modelName, idValue); } catch(Exception e) { LOG.error("writeBackIdValueFromModel error.", e); } finally { RedisDAO.returnResource(jedis); } return result; } public boolean writeBackIdValue(String modelName, Long idValue) { String sqlCount = "select count(*) from sangame_ids where model=?"; String sqlInsert = "insert sangame_ids(model, idvalue, time_insert) values(?, ?, CURRENT_TIMESTAMP)"; String sqlUpdate = "update sangame_ids set idvalue=? where model=? and idvalue<?"; if(MySqlDAO.simpleDb().queryForLong(sqlCount, modelName) > 0) { MySqlDAO.simpleDb().executeUpdate(sqlUpdate, idValue, modelName, idValue); }else{ MySqlDAO.simpleDb().executeUpdate(sqlInsert, modelName, idValue); LOG.info("Initial ids fro model {} with {}.", modelName, idValue);; } return true; } }
2、反射写入DB的核心代码
String SQL_INSERT = null; String[] INSERT_PROPERTIES = null; SQLOperation insertEntity(Object entity) throws Exception { if (SQL_INSERT==null) { StringBuilder sb = new StringBuilder(128); sb.append("insert into ").append(this.tableName).append(" ("); String[] properties = this.mappings.keySet().toArray(new String[0]); //Arrays.sort(properties); List<String> insertableProperties = new LinkedList<String>(); for (String property : properties) { PropertyMapping pm = mappings.get(property); if (pm.insertable) { insertableProperties.add(property); sb.append(pm.columnName).append(','); } } //append fixed column sb.append("time_insert,"); // set last ',' to ')': sb.setCharAt(sb.length()-1, ')'); sb.append(" values ("); for (int i=0; i<insertableProperties.size(); i++) { sb.append("?,"); } //append fixed column time_insert sb.append("CURRENT_TIMESTAMP,"); // set last ',' to ')': sb.setCharAt(sb.length()-1, ')'); SQL_INSERT = sb.toString(); INSERT_PROPERTIES = insertableProperties.toArray(new String[insertableProperties.size()]); } Object[] params = new Object[INSERT_PROPERTIES.length]; for (int i=0; i<INSERT_PROPERTIES.length; i++) { params[i] = mappings.get(INSERT_PROPERTIES[i]).get(entity); } return new SQLOperation(SQL_INSERT, params); }
class PropertyMapping { final String property; final Field field; final boolean insertable; final boolean updatable; final String columnName; final String columnDefinition; final boolean nullable; final boolean id; final Method getter; final Method setter; @SuppressWarnings("rawtypes") final Class enumClass; // public PropertyMapping(Method getter, Method setter) { // this.field = null; // this.property = Utils.getGetterName(getter); // this.getter = getter; // this.setter = setter; // this.enumClass = getter.getReturnType().isEnum() ? getter.getReturnType() : null; // Column column = getter.getAnnotation(Column.class); // this.insertable = column==null ? true : column.insertable(); // this.updatable = column==null ? true : column.updatable(); // this.columnName = column==null ? Utils.getGetterName(getter) : ("".equals(column.name()) ? Utils.getGetterName(getter) : column.name()); // this.columnDefinition = column==null ? "" : column.columnDefinition(); // this.nullable = column==null ? true : column.nullable(); // this.id = getter.isAnnotationPresent(Id.class); // } public PropertyMapping(Field field, Method getter, Method setter) { this.field = field; this.getter = getter; this.setter = setter; this.enumClass = field.getType().isEnum() ? field.getType() : null; Column column = field.getAnnotation(Column.class); this.insertable = column==null ? true : column.insertable(); this.updatable = column==null ? true : column.updatable(); this.columnName = column==null ? field.getName() : ("".equals(column.name()) ? field.getName() : column.name()); this.columnDefinition = column==null ? Utils.getColumnDefinition(field.getType()) : column.columnDefinition().isEmpty()?Utils.getColumnDefinition(field.getType()):column.columnDefinition(); this.nullable = column==null ? true : column.nullable(); this.id = field.isAnnotationPresent(Id.class); this.property = field.getName(); } @SuppressWarnings("unchecked") Object get(Object target) throws Exception { Object r; if(getter==null) { r = field.get(target); } else { r = getter.invoke(target); } if(enumClass!=null) r = Enum.valueOf(enumClass, (String) r); else if(!Utils.isSupportedSQLObject(field.getType())) { r = PojoMapper.toJson(r, false); } return r; } @SuppressWarnings("unchecked") void set(Object target, Object value) throws Exception { if (enumClass!=null && value!=null) { value = Enum.valueOf(enumClass, (String) value); } else if(!Utils.isSupportedSQLObject(field.getType())) { value = PojoMapper.fromJson(value.toString(), field.getType()); //value = PojoMapper.fromJson(value.toString(), field.getDeclaringClass()); } if(setter==null) { field.set(target, value); } else { setter.invoke(target, value); } } }
/** * Create an entity in database, writing all insertable properties. * * @param entity Entity object instance. */ public void create(Object entity) { EntityOperation<?> op = getEntityOperation(entity.getClass()); SQLOperation sqlo = null; try { sqlo = op.insertEntity(entity); } catch (Exception e) { throw new RuntimeException(e); } jdbcTemplate.update(sqlo.sql, sqlo.params); }