/**
* @Project: hehenian-biz-service Maven Webapp
* @Package com.hehenian.biz.service.account
* @Title: UserInfoServiceImpl.java
* @Description: 用户信息服务接口 替代UserServiceImpl
*
* @author: zhanbmf
* @date 2015-3-29 下午2:06:47
* @Copyright: HEHENIAN Co.,Ltd. All rights reserved.
* @version V1.0
*/
package com.hehenian.biz.service.account;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.hehenian.biz.common.account.IUserInfoService;
import com.hehenian.biz.common.account.dataobject.LoginInfoRelate;
import com.hehenian.biz.common.util.SqlUtils;
import com.hehenian.biz.common.util.UserHelper;
import com.hehenian.biz.dal.account.IUserInfoDao;
import com.hehenian.common.redis.CacheService;
@Service("userInfoService")
public class UserInfoServiceImpl implements IUserInfoService {
private static Logger logger = Logger.getLogger("user");
@Autowired
private IUserInfoDao userInfoDao;
@Autowired
private CacheService redisCacheService;
private static final String IN_CACHE = "in cache";
private static final String NOT_USE_CACHE = "not use cache";
private static final String DELETE_CACHE = "delete cache";
private static final String DELETE_ALL_CACHE = "delete all cache";
private static final String ERROR = "error";
private static final String SUCCESS = "success";
private static final String NULL = "get null";
private final int expireTime = 60 * 15;
@Override
public <T> T get(int userId, Class<T> clazz, boolean isRealTime) {
long startTime = System.currentTimeMillis();
String info = NOT_USE_CACHE;
try {
if (userId < 0) {
info = ERROR;
return null;
}
// UserXXX是联合主键不能根据userId直接取
if (clazz.getSimpleName().equalsIgnoreCase("UserXXX")) {
info = " not provide for UserContact ";
return null;
}
// 非实时优先取缓存返回
if (!isRealTime) {
T cacheObject = (T) redisCacheService.get().get(clazz.getName() + userId);
if (cacheObject != null) {
info = IN_CACHE;
return cacheObject;
}
}
// 查询数据库
List<T> queryToListObject = userInfoDao.queryToListObject(SqlUtils.getSql(userId, clazz), clazz, isRealTime);
if (queryToListObject == null || queryToListObject.size() == 0) {
info = NULL;
return null;
}
T result = queryToListObject.get(0);
// 添加缓存
redisCacheService.get().set(clazz.getName() + userId, result, expireTime);
return result;
} finally {
long endTime = System.currentTimeMillis() - startTime;
logger.info(new StringBuilder("get() ")
.append(clazz.getSimpleName()).append(" id=")
.append(userId).append(",time=").append(endTime)
.append(",info=").append(info).toString());
}
}
@Override
public <T> int insert(T t) {
long startTime = System.currentTimeMillis();
String info = NOT_USE_CACHE;
int userId = -1;
try {
// 获取用户id用于分表
userId = getUserIdForAction(t);
if (userId < 0) {
info = ERROR;
return 0;
}
// 插入数据库
int result = userInfoDao.update(SqlUtils.getInsertSql(userId, t));
if (result != 0) {
// 成功,马上更新缓存
info = SUCCESS;
this.get(userId, t.getClass(), true);
} else {
info = ERROR;
}
return result;
} finally {
long endTime = System.currentTimeMillis() - startTime;
logger.info(new StringBuilder("insert() ")
.append(t.getClass().getSimpleName()).append(" id=")
.append(userId).append(",time=").append(endTime)
.append(",info=").append(info).toString());
}
}
@Override
public <T> int update(T t, boolean clearCache) {
long startTime = System.currentTimeMillis();
String info = NOT_USE_CACHE;
int userId = -1;
try {
// 因为使用邮件手机号码分表,不能直接更新LoginInfoRelate类.只能通过insert+delete
if (t instanceof LoginInfoRelate) {
return 0;
}
// 获取用户id用于分表
userId = getUserIdForAction(t);
if (userId < 0) {
info = ERROR;
return 0;
}
// 获取表的主键用于设置where语句
Map<String, String> primaryKeyValue = getPrimaryKeyValue(t);
// 获取旧数据库对象
T old = (T) get(getUserIdByQuery(t, true), t.getClass(), true);
// 比较新旧对象获取更新sql
String updateSql = SqlUtils.getUpdateSql(userId, primaryKeyValue, old, t);
// 不需要更新
if (updateSql == null) {
info = SUCCESS;
return 1;
}
// 执行更新
int result = userInfoDao.update(updateSql);
if (result != 0) {
// 需要清空缓存防止脏数据(只有客户端更换resin请求才会触发)
if (clearCache) {
info = DELETE_ALL_CACHE;
redisCacheService.clear(t.getClass().getName() + userId);
}
// 成功,马上更新缓存
this.get(userId, t.getClass(), true);
info = SUCCESS;
} else {
info = ERROR;
}
return result;
} finally {
long endTime = System.currentTimeMillis() - startTime;
logger.info(new StringBuilder("update() ")
.append(t.getClass().getSimpleName()).append(" id=")
.append(userId).append(",time=").append(endTime)
.append(",info=").append(info).append(",clearCache=")
.append(clearCache).toString());
}
}
@Override
public <T> int updateKeys(T dest, T src, boolean clearCache) {
long startTime = System.currentTimeMillis();
String info = NOT_USE_CACHE;
int userId = -1;
try {
// 因为使用邮件手机号码分表,不能直接更新LoginInfoRelate类.只能通过insert+delete
if (dest instanceof LoginInfoRelate) {
return 0;
}
// 获取用户id用于分表
userId = getUserIdForAction(dest);
if (userId < 0) {
info = ERROR;
return 0;
}
// 获取表的主键用于设置where语句
Map<String, String> primaryKeyValue = getPrimaryKeyValue(src);
// 比较新旧对象获取更新sql
String updateSql = SqlUtils.getUpdateSql(userId, primaryKeyValue, src, dest);
// 不需要更新
if (updateSql == null) {
info = SUCCESS;
return 1;
}
// 执行更新
int result = userInfoDao.update(updateSql);
if (result != 0) {
// 需要清空缓存防止脏数据(只有客户端更换resin请求才会触发)
if (clearCache) {
info = DELETE_ALL_CACHE;
redisCacheService.clear(dest.getClass().getName() + userId);
}
// 成功,马上更新缓存
// 添加缓存
redisCacheService.get().set(getCacheKey(dest), result, expireTime);
info = SUCCESS;
} else {
info = ERROR;
}
return result;
} finally {
long endTime = System.currentTimeMillis() - startTime;
logger.info(new StringBuilder("updateKeys() ")
.append(dest.getClass().getSimpleName()).append(" id=")
.append(userId).append(",time=").append(endTime)
.append(",info=").append(info).append(",clearCache=")
.append(clearCache).toString());
}
}
@Override
public <T> int insertOrUpdate(T t, boolean clearCache) {
// 查询数据库是否存在
Object object = get(getUserIdByQuery(t, true), t.getClass(), true);
if (object == null) {
return insert(t);
} else {
return update(t, clearCache);
}
}
@Override
public <T> int delete(int id, Class<T> clazz) {
long startTime = System.currentTimeMillis();
String info = SUCCESS;
try {
int result = userInfoDao.update(SqlUtils.getDeleteSql(id, clazz));
if (result != 0) {
info = DELETE_CACHE;
// 成功,马上删除缓存
redisCacheService.clear(clazz.getName() + id);
} else {
info = ERROR;
}
return result;
} finally {
long endTime = System.currentTimeMillis() - startTime;
logger.info(new StringBuilder("delete() ")
.append(clazz.getSimpleName()).append(" id=").append(id)
.append(",time=").append(endTime).append(",info=")
.append(info).toString());
}
}
@Override
public <T> int deleteByKeys(T t) {
long startTime = System.currentTimeMillis();
String info = SUCCESS;
int userId = -1;
try {
// 获取用户id用于分表
userId = getUserIdForAction(t);
if (userId < 0) {
return 0;
}
// 获取表的主键用于设置where语句
Map<String, String> primaryKeyValue = getPrimaryKeyValue(t);
int result = userInfoDao.update(SqlUtils.getDeleteSql(userId, primaryKeyValue, t.getClass()));
if (result != 0) {
info = DELETE_CACHE;
// 成功,马上删除缓存
redisCacheService.clear(t.getClass().getName() + userId);
}
return result;
} finally {
long endTime = System.currentTimeMillis() - startTime;
logger.info(new StringBuilder("deleteByKeys() ")
.append(t.getClass().getSimpleName()).append(" id=")
.append(userId).append(",time=").append(endTime)
.append(",info=").append(info).toString());
}
}
@Override
public <T> List<T> getList(int[] ids, Class<T> clazz, boolean isRealTime) {
List<T> list = new ArrayList<T>();
for (int i = 0; i < ids.length; i++) {
// 为空也写入返回
list.add(get(ids[i], clazz, isRealTime));
}
return list;
}
@Override
public <T> Map<Integer, Integer> insertList(List<T> list) {
if (list == null || list.size() == 0) {
return null;
}
long startTime = System.currentTimeMillis();
StringBuilder info = new StringBuilder();
Class<?> clazz = list.get(0).getClass();
List<Integer> temp = new ArrayList<Integer>();
try {
// 根据userId组装不同的sql
String[] sqls = new String[list.size()];
Map<Integer, Integer> result = new HashMap<Integer, Integer>();
for (int i = 0; i < sqls.length; i++) {
T t = list.get(i);
int userId = getUserIdForAction(t);
sqls[i] = SqlUtils.getInsertSql(userId, t);
temp.add(userId);
}
// 批量更新
int[] batchUpdate = userInfoDao.batchUpdate(sqls);
if (batchUpdate == null || batchUpdate.length == 0) {
return null;
}
// 批量组装结果
for (int i = 0; i < temp.size(); i++) {
Integer userId = temp.get(i);
// 执行成功添加缓存
if (batchUpdate[i] > 0) {
this.get(userId, list.get(i).getClass(), true);
result.put(userId, 1);
info.append(userId).append(":").append(SUCCESS).append(",");
} else {
result.put(userId, 0);
info.append(userId).append(":").append(ERROR).append(",");
}
}
return result;
} finally {
long endTime = System.currentTimeMillis() - startTime;
logger.info(new StringBuilder("insertList() ")
.append(clazz.getSimpleName()).append(" ids=")
.append(Arrays.toString(temp.toArray())).append(",time=")
.append(endTime).append(",info=").append(info).toString());
}
}
@Override
public <T> Map<Integer, Integer> updateList(List<T> list, boolean clearCache) {
if (list == null || list.size() == 0) {
return null;
}
long startTime = System.currentTimeMillis();
StringBuilder info = new StringBuilder();
Class<?> clazz = list.get(0).getClass();
List<Integer> temp = new ArrayList<Integer>();
try {
// 根据userId组装不同的sql
String[] sqls = new String[list.size()];
Map<Integer, Integer> result = new HashMap<Integer, Integer>();
for (int i = 0; i < sqls.length; i++) {
T t = list.get(i);
int userId = getUserIdByQuery(t, true);
T old = (T) get(userId, list.get(i).getClass(), true);
sqls[i] = SqlUtils.getUpdateSql(getUserIdForAction(t), getPrimaryKeyValue(t), old, t);
temp.add(userId);
}
// 批量更新
int[] batchUpdate = userInfoDao.batchUpdate(sqls);
if (batchUpdate == null || batchUpdate.length == 0) {
return null;
}
// 批量组装结果
for (int i = 0; i < temp.size(); i++) {
Integer userId = temp.get(i);
// 执行成功添加缓存
if (batchUpdate[i] > 0) {
// 需要清空缓存防止脏数据(只有客户端更换resin请求才会触发)
if (clearCache) {
redisCacheService.clear(list.get(i).getClass().getName() + userId);
}
this.get(userId, list.get(i).getClass(), true);
result.put(userId, 1);
info.append(userId).append(":").append(SUCCESS).append(",");
} else {
result.put(userId, 0);
info.append(userId).append(":").append(ERROR).append(",");
}
}
return result;
} finally {
long endTime = System.currentTimeMillis() - startTime;
logger.info(new StringBuilder("updateList() ")
.append(clazz.getSimpleName()).append(" ids=")
.append(Arrays.toString(temp.toArray())).append(",time=")
.append(endTime).append(",info=").append(info).toString());
}
}
@Override
public <T> Map<Integer, Integer> deleteList(List<T> list) {
if (list == null || list.size() == 0) {
return null;
}
long startTime = System.currentTimeMillis();
String info = SUCCESS;
Class<?> clazz = list.get(0).getClass();
List<Integer> temp = new ArrayList<Integer>();
try {
// 根据userId组装不同的sql
String[] sqls = new String[list.size()];
Map<Integer, Integer> result = new HashMap<Integer, Integer>();
for (int i = 0; i < sqls.length; i++) {
int userId = getUserIdByQuery(list.get(i), true);
sqls[i] = SqlUtils.getDeleteSql(userId, list.get(i).getClass());
temp.add(userId);
}
int[] batchUpdate = userInfoDao.batchUpdate(sqls);
for (int i = 0; i < temp.size(); i++) {
Integer userId = temp.get(i);
if (batchUpdate[i] != -1) {
// 成功,马上删除缓存
info = DELETE_ALL_CACHE;
redisCacheService.clear(list.get(i).getClass().getName() + userId);
result.put(userId, 1);
} else {
info = ERROR;
result.put(userId, 0);
}
}
return result;
} finally {
long endTime = System.currentTimeMillis() - startTime;
logger.info(new StringBuilder("deleteList() ")
.append(clazz.getSimpleName()).append(" ids=")
.append(Arrays.toString(temp.toArray())).append(",time=")
.append(endTime).append(",info=").append(info).toString());
}
}
@Override
public List<Map<String, Object>> queryToListMap(String sql, int id,
boolean isRealTime) {
long startTime = System.currentTimeMillis();
String info = SUCCESS;
try {
// 非实时优先取缓存返回
if (!isRealTime) {
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
List<Object> cacheObject = redisCacheService.get().getListAll(sql);
if (cacheObject != null) {
info = IN_CACHE;
for (Object object : cacheObject) {
Map<String, Object> map = (Map<String, Object>) object;
list.add(map);
}
return list;
}
}
List<Map<String, Object>> result = userInfoDao.queryToListMap(SqlUtils.getQuerySql(sql, id), isRealTime);
// 添加缓存
redisCacheService.get().set(sql, result, expireTime);
return result;
} finally {
long endTime = System.currentTimeMillis() - startTime;
logger.info(new StringBuilder("queryToListMap() ").append(" id=")
.append(id).append(",sql=").append(sql).append(",time=")
.append(endTime).append(",info=").append(info).toString());
}
}
@Override
public <T> List<T> queryToListObject(String sql, int id, Class<T> clazz,
boolean isRealTime) {
long startTime = System.currentTimeMillis();
String info = SUCCESS;
try {
// 非实时优先取缓存返回
if (!isRealTime) {
List<T> cacheObject = (List<T>) redisCacheService.get().getListAll(sql);
if (cacheObject != null) {
info = IN_CACHE;
return cacheObject;
}
}
List<T> result = userInfoDao.queryToListObject(sql, clazz, isRealTime);
// 添加缓存
redisCacheService.get().set(sql, result, expireTime);
return result;
} finally {
long endTime = System.currentTimeMillis() - startTime;
logger.info(new StringBuilder("queryToListObject() ")
.append(" id=").append(id).append(",sql=").append(sql)
.append(",time=").append(endTime).append(",info=")
.append(info).toString());
}
}
@Override
public <T> Integer queryCount(String sql, int id, Class<T> clazz, boolean isRealTime) {
long startTime = System.currentTimeMillis();
String info = SUCCESS;
try {
// 非实时优先取缓存返回
if (!isRealTime) {
Integer cacheObject = (Integer) redisCacheService.get().get(sql);
if (cacheObject != null) {
info = IN_CACHE;
return cacheObject;
}
}
int result = userInfoDao.queryForInt(sql, isRealTime);
if (result > 0) {// 执行成功
// 添加缓存
redisCacheService.get().set(sql, result, expireTime);
} else {
info = ERROR;
}
return result;
} finally {
long endTime = System.currentTimeMillis() - startTime;
logger.info(new StringBuilder("queryCount() ").append(" id=")
.append(id).append(",sql=").append(sql).append(",time=")
.append(endTime).append(",info=").append(info).toString());
}
}
/**
* 根据用户邮箱、电话查询用户id
* @param loginInfo
* @param isRealTime
* @return
*/
private int getUserIdByOthers(String loginInfo, boolean isRealTime) {
int tableId = UserHelper.getTableNumberByDigest(loginInfo);
int result = userInfoDao.queryForInt(SqlUtils.getUserIdFromloginInfo(tableId, loginInfo, LoginInfoRelate.class), isRealTime);
if (result == -1) {
logger.info("*******logininfo not exist: " + loginInfo);
}
return result;
}
@Override
public <T> T getByLoginInfo(String loginInfo, Class<T> clazz, boolean isRealTime) {
String sql;
int id = -1;
long startTime = System.currentTimeMillis();
String info = NOT_USE_CACHE;
try {
// 需要查询自身
if (clazz.equals(LoginInfoRelate.class)) {
// 获取id用于分表
id = UserHelper.getTableNumberByDigest(loginInfo);
if (id < 0) {
return null;
}
sql = SqlUtils.getSqlForloginInfo(id, loginInfo, clazz);
} else {
// 需要根据loginInfo查询其他的类
// 从数据库表LoginInfoRelate查询获得用户id
id = getUserIdByOthers(loginInfo, true);
// 根据用户id获得查询指定表sql
sql = SqlUtils.getSql(id, clazz);
}
// 非实时优先取缓存返回
if (!isRealTime) {
T cacheObject = (T) redisCacheService.get().get(clazz.getName() + id);
if (cacheObject != null) {
info = IN_CACHE;
return cacheObject;
}
}
// 查询指定类
List<T> queryToListObject = userInfoDao.queryToListObject(sql, clazz, isRealTime);
if (queryToListObject == null || queryToListObject.size() == 0) {
return null;
}
T result = queryToListObject.get(0);
// 添加缓存
redisCacheService.get().set(clazz.getName() + id, result, expireTime);
return result;
} finally {
long endTime = System.currentTimeMillis() - startTime;
logger.info(new StringBuilder("getByLoginInfo() ")
.append(clazz.getSimpleName()).append(" id=").append(id)
.append(",time=").append(endTime).append(",info=")
.append(info).toString());
}
}
@Override
public <T> Map<String, T> getListByLoginInfo(String[] loginInfo, Class<T> clazz, boolean isRealTime) {
Map<String, T> map = new HashMap<String, T>();
for (int i = 0; i < loginInfo.length; i++) {
map.put(loginInfo[i], getByLoginInfo(loginInfo[i], clazz, isRealTime));
}
//to do...
return map;
}
/**
* 获取用户id,用于进行分表
* @param t
* @return
*/
private <T> int getUserIdForAction(T t) {
if (t instanceof LoginInfoRelate) {
// LoginInfoRelate 需要由字符串转换为整型
return UserHelper.getTableNumberByDigest(((LoginInfoRelate) t).getLoginInfo());
}
return -1;
}
/**
* 获取用户id,用于进行分表
* @param t
* @param isRealTime
* @return
*/
private <T> int getUserIdByQuery(T t, boolean isRealTime) {
if (t instanceof LoginInfoRelate) {
// 需要查询LoginInfoRelate才能获得用户id
return getUserIdByOthers(((LoginInfoRelate) t).getLoginInfo(), isRealTime);
}
//to do...
return -1;
}
/**
* 获取主键
*
* @param t
* @return
*/
private <T> Map<String, String> getPrimaryKeyValue(T t) {
Map<String, String> map = new HashMap<String, String>();
if (t instanceof LoginInfoRelate) {
if (((LoginInfoRelate) t).getId() > 0) {
map.put("id", String.valueOf(((LoginInfoRelate) t).getId()));
}
}
//to do...
return map;
}
/**
* 获取缓存键
* @param clazz
* @param t
* @return
*/
private <T> String getCacheKey(T t) {
int id = -1;
if (t instanceof LoginInfoRelate) {
if (((LoginInfoRelate) t).getId() > 0) {
id = ((LoginInfoRelate) t).getId();
return t.getClass().getName() + id;
}
} else {
return "-1";
}
//to do...
return t.getClass().getName() + id;
}
}