高併發下的基礎優化(三)——訂單主鍵(終)
阿新 • • 發佈:2019-02-12
具體不說了,看上一篇。
開發框架spring4.2.9-springmvc-hibernate4.3.11Final,需要包的可以在我的資源裡找。
由於這些類都要封裝進dao基類中,所以就不交給spring管理了,註解都去掉。
方便大家參考依賴,保留import,看別人的程式碼不貼上依賴,那麼多同名的包,誰知道要用哪個。
import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.ReentrantReadWriteLock; import …….util.localcache.LocalCacheUtil; /** * 主鍵生成基類 * @author 瘋狂的蚯蚓 * */ public class IdGenerator { /** * AtomicInteger是一個提供原子操作的Integer類,通過執行緒安全的方式操作加減。 */ protected AtomicInteger value; protected String time; /** * 讀寫鎖 */ protected ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); public String getSplitString() { return ""; } public int getInitial() { return 0; } public String getPrefix() { String result = null; try { //查詢伺服器的配置檔案 result = (String)LocalCacheUtil.query(PropertiesFileIOUtil.MECHINE_CODE_KEY); if(result==null) { Map<String, String> map = PropertiesFileIOUtil.loadProps(); if(map==null || !map.containsKey(PropertiesFileIOUtil.MECHINE_CODE_KEY)) { return ""; } //伺服器號 result = map.get(PropertiesFileIOUtil.MECHINE_CODE_KEY); //加入本地快取 LocalCacheUtil.put(PropertiesFileIOUtil.MECHINE_CODE_KEY, result); } } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("獲取主鍵字首失敗"); } return result; } public int getRollingInterval() { return 1; } }
/** * Id生成器配置介面 * @author 瘋狂的蚯蚓 * */ public interface IdGeneratorConfig { /** * 獲取分隔符 * @return */ String getSplitString(); /** * 獲取初始值 * @return */ int getInitial(); /** * 獲取ID字首 * @return */ String getPrefix(); /** * 獲取滾動間隔, 單位: 秒 * @return */ int getRollingInterval(); }
import java.util.Map; import …….util.localcache.LocalCacheUtil; /** * 主鍵生成配置實現類 * @author 瘋狂的蚯蚓 * */ public class DefaultIdGeneratorConfig implements IdGeneratorConfig { @Override public String getSplitString() { return ""; } @Override public int getInitial() { return 1; } @Override public String getPrefix() { String result = null; try { //查詢伺服器的配置檔案 result = (String)LocalCacheUtil.query(PropertiesFileIOUtil.MECHINE_CODE_KEY); if(result==null) { Map<String, String> map = PropertiesFileIOUtil.loadProps(); if(map==null || !map.containsKey(PropertiesFileIOUtil.MECHINE_CODE_KEY)) { return ""; } //伺服器號 result = map.get(PropertiesFileIOUtil.MECHINE_CODE_KEY); //加入本地快取 LocalCacheUtil.put(PropertiesFileIOUtil.MECHINE_CODE_KEY, result); } } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("獲取主鍵字首失敗"); } return result; } @Override public int getRollingInterval() { return 1; } }
快取啥的就自己去研究了,很簡單,沒幾行程式碼,以下是配置檔案的讀取,當然其他方法都行,不一定要存檔案
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
/**
* 讀取配置檔案工具類
* @author 瘋狂的蚯蚓
*
*/
public class PropertiesFileIOUtil
{
/**
* 機器號程式碼
*/
public static final String MECHINE_CODE_KEY = "MechineCode";
public static Properties props;
public static Map<String, String> loadProps()
{
Map<String, String> result = new HashMap<String, String>();
props = new Properties();
InputStream in = null;
try
{
//第一種,通過類載入器進行獲取properties檔案流
//in = PropertyUtil.class.getClassLoader().getResourceAsStream("sysConfig.properties");
//第二種,通過類進行獲取properties檔案流
in = PropertiesFileIOUtil.class.getClassLoader().getResourceAsStream("config/mechineCode.properties");
props.load(in);
String mechineCode = props.getProperty(MECHINE_CODE_KEY);
// System.out.println("mechineCode="+mechineCode);
result.put(MECHINE_CODE_KEY, mechineCode);
}
catch (FileNotFoundException e)
{
e.printStackTrace();
//logger.error("sysConfig.properties檔案未找到");
}
catch (IOException e)
{
e.printStackTrace();
//logger.error("出現IOException");
}
finally
{
try
{
if(null != in)
{
in.close();
}
}
catch (IOException e)
{
//logger.error("sysConfig.properties檔案流關閉出現異常");
}
}
//logger.info("載入properties檔案內容完成...........");
//logger.info("properties檔案內容:" + props);
return result;
}
public String getProperty(String key)
{
if(null == props)
{
loadProps();
}
return props.getProperty(key);
}
public String getProperty(String key, String defaultValue)
{
if(null == props)
{
loadProps();
}
return props.getProperty(key, defaultValue);
}
}
以下是dao基類介面
import java.io.Serializable;
import java.util.List;
import …….vo.ComboBox;
import …….vo.Pagination;
/**
* 通用Dao介面
*
* @param <T> 實體物件類
* @param <PK> 主鍵
*/
public interface GenericDao<T, PK extends Serializable> {
/**
* 根據主鍵獲得一個實體物件
*
* @param id
* @return
*/
public T findById(PK id);
/**
* 獲得表中的所有實體物件
*
* @return
*/
public List<T> findAll();
/**
* 新增一個實體物件
*
* @param entity
* @return
*/
public T save(T entity);
/**
* 更新一個實體物件
*
* @param entity
*/
public void update(T entity);
/**
* 刪除一個實體物件
*
* @param entity
*/
public void delete(T entity);
/**
* 根據HQL語句和查詢條件,獲得具體數量
*
* @param hql 不需要也不能寫select count(*),直接從from開始寫
* @param params
* @return
*/
public Long countByHQL(String hql, Object[] params);
/**
* 根據HQL語句和查詢條件,獲得一個實體物件
*
* @param hql
* @param params
* @return
*/
public T getEntityByHQL(String hql, Object[] params);
/**
* 根據HQL語句和查詢條件,獲得多個實體物件
*
* @param hql
* @param params
* @return
*/
public List<T> listEntityByHQL(String hql, Object[] params);
/**
* 根據HQL語句和查詢條件,獲得多個實體物件,分頁顯示,可排序
*
* @param hql
* 必須是查詢整個model類的資訊,不能只查詢部分欄位 正確寫法:from 類名 where 條件 order by
* 錯誤寫法:select 表名(欄位名) from 類名 where 條件
* @param params
* @param pageSize
* 每頁顯示記錄數
* @param pageNumber
* 當前第幾頁
* @return
*/
public Pagination listEntityByHQL(String hql, Object[] params,Integer pageSize, Integer pageNumber);
public Pagination listEntityByHQL1(String hql, Object[] params,
Integer pageSize, Integer pageNumber);
public Pagination listEntityByHQLbox(String hql, Object[] params,
Integer pageSize, Integer pageNumber);
/**
* 根據SQL語句和查詢條件,獲得多個實體物件,分頁顯示,可排序
*
* @param sql
* @param params
* @param pageSize
* 每頁顯示記錄數
* @param pageNumber
* 當前第幾頁
* @return
*/
public Pagination listEntityBySQL(String sql, Object[] params,Integer pageSize, Integer pageNumber);
/**
* 執行刪除或者更新的HQL語句
*
* @param hql
* @param params
* @return
*/
public Integer updateByHQL(String hql, Object[] params);
/**
* 執行刪除或者更新的SQL語句
*
* @param sql
* @param params
* @return
*/
public Integer updateBySQL(String sql, Object[] params);
/**
* 根據任意的select語句,獲得對應列的物件陣列
* @param hql
* @param params
* @return
*/
public List<Object[]> listEntityBySelect(String hql, Object[] params);
/**
* 根據HQL語句和查詢條件,獲得實體物件中一個欄位的所有值的集合
* @param hql
* @param params
* @return easyui-combobox格式的vo類
*/
public List<ComboBox> listFieldByHQL(String hql, Object[] params);
/**
* 通過sql語句,查詢結果對映成實體
* @param sql
* @param c 結果要對映的實體物件
* @return
*/
@SuppressWarnings("rawtypes")
List listEntityBySql(String sql,Class c);
/**
* 獲取下一個主鍵,預設是從1開始遞增,如果有特殊需求需要在dao實現中重寫該方法
* @return
*/
public String next();
}
主鍵生成方法在該類的最底部,還有不完善的大家直接去修修補補,優化提升import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import javax.annotation.Resource;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.springframework.orm.hibernate4.HibernateCallback;
import org.springframework.orm.hibernate4.HibernateTemplate;
import …….dao.GenericDao;
import …….idgenerator.IdGenerator;
import …….vo.ComboBox;
import …….vo.Pagination;
public class GenericDaoHibernate<T, PK extends Serializable> extends IdGenerator
implements GenericDao<T, PK> ,Runnable
{
private final Class<T> clazz;
protected HibernateTemplate hibernateTemplate;
@SuppressWarnings("unchecked")
public GenericDaoHibernate() {
clazz = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
value = new AtomicInteger(getInitial());
}
public HibernateTemplate getHibernateTemplate() {
return hibernateTemplate;
}
@Resource()
public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
this.hibernateTemplate = hibernateTemplate;
}
@Override
public T findById(PK id) {
return this.hibernateTemplate.get(clazz, id);
}
@SuppressWarnings("unchecked")
@Override
public List<T> findAll() {
return (List<T>) this.hibernateTemplate.find("from " + clazz.getName());
}
@Override
public T save(T entity) {
this.hibernateTemplate.persist(entity);
return entity;
}
@Override
public void update(T entity) {
this.hibernateTemplate.merge(entity);
}
@Override
public void delete(T entity) {
this.hibernateTemplate.delete(entity);
}
/**
* 根據HQL語句和查詢條件,獲得一個物件
* 例:分頁時查詢出總的記錄數
*
* @param hql
* @param params
* @return
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
private Object queryObjectByHQL(final String hql, final Object[] params) {
Object obj = this.hibernateTemplate.execute(new HibernateCallback() {
@Override
public Object doInHibernate(Session session) throws HibernateException {
Query query = session.createQuery(hql);
if (params != null) {
for (int i = 0; i < params.length; i++) {
query.setParameter(i, params[i]);
}
}
return query.uniqueResult();
}
});
return obj;
}
/**
* 根據SQL語句和查詢條件,獲得一個物件
* 例:分頁時查詢出總的記錄數
*
* @param hql
* @param params
* @return
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
private Object queryObjectBySQL(final String sql, final Object[] params) {
Object obj = this.hibernateTemplate.execute(new HibernateCallback() {
@Override
public Object doInHibernate(Session session) throws HibernateException {
Query query = session.createSQLQuery(sql);
if (params != null) {
for (int i = 0; i < params.length; i++) {
query.setParameter(i, params[i]);
}
}
return query.uniqueResult();
}
});
return obj;
}
@Override
public Long countByHQL(String hql, Object[] params) {
// 拼接成新的hql字串,用於查詢總共多少條資料, 如果有order by要擷取掉,因為有的資料庫不支援
String nhql = "select count(*) " + hql.split(" order by")[0];
return (Long) this.queryObjectByHQL(nhql, params); // 獲得總的記錄數
}
public Long countBySQL(String sql, Object[] params) {
// 拼接成新的hql字串,用於查詢總共多少條資料, 如果有order by要擷取掉,因為有的資料庫不支援
String nhql = "select count(*) from (" + sql.split(" order by")[0] + ")";
/*
* 獲得總的記錄數
* Hibernate 執行SQL語句的count函式返回型別
* oracle :BigDecimal
* db2 : Integer
*/
Object obj = this.queryObjectBySQL(nhql, params);
String objName = obj.getClass().getName();
if("java.math.BigDecimal".equals(objName)) {
BigDecimal bq = (BigDecimal) obj;
return bq.longValue();
}else if("java.lang.Integer".equals(objName)){
Integer bq = (Integer) this.queryObjectBySQL(nhql, params);
return bq.longValue();
}else {
return 0L;
}
}
@Override
public T getEntityByHQL(String hql, Object[] params)
{
@SuppressWarnings("unchecked")
List<T> list = (List<T>) this.hibernateTemplate.find(hql, params);
if (list != null && list.size() > 0)
{
return list.get(0);
}
else
{
return null;
}
}
@SuppressWarnings("unchecked")
@Override
public List<T> listEntityByHQL(String hql, Object[] params)
{
return (List<T>) this.hibernateTemplate.find(hql, params);
}
/**
* 分頁查詢
*
* @param hql
* @param params
* @param pageSize
* @param pageNumber
* @param totalCount
* @return
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
private Pagination getPaginationByHQL(final String hql, final Object[] params, final Integer pageSize,
final Integer pageNumber, final Long totalCount) {
return (Pagination) this.hibernateTemplate.execute(new HibernateCallback() {
@Override
public Object doInHibernate(Session session) throws HibernateException {
Pagination pagination = new Pagination(pageSize, pageNumber, totalCount);
Query query = session.createQuery(hql);
if (params != null) {
for (int i = 0; i < params.length; i++) {
query.setParameter(i, params[i]);
}
}
query.setFirstResult(pageSize * (pageNumber - 1));
query.setMaxResults(pageSize);
pagination.setList(query.list());
return pagination;
}
});
}
/**
* 分頁查詢
*
* @param sql
* @param params
* @param pageSize
* @param pageNumber
* @param totalCount
* @return
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
private Pagination getPaginationBySQL(final String sql, final Object[] params, final Integer pageSize,
final Integer pageNumber, final Long totalCount) {
return (Pagination) this.hibernateTemplate.execute(new HibernateCallback() {
@Override
public Object doInHibernate(Session session) throws HibernateException {
Pagination pagination = new Pagination(pageSize, pageNumber, totalCount);
Query query = session.createSQLQuery(sql);
if (params != null) {
for (int i = 0; i < params.length; i++) {
query.setParameter(i, params[i]);
}
}
query.setFirstResult(pageSize * (pageNumber - 1));
query.setMaxResults(pageSize);
pagination.setList(query.list());
return pagination;
}
});
}
@Override
public Pagination listEntityByHQL(String hql, Object[] params, Integer pageSize, Integer pageNumber) {
long totalCount = this.countByHQL(hql, params);
return this.getPaginationByHQL(hql, params, pageSize, pageNumber, totalCount);
}
@Override
public Pagination listEntityBySQL(String hql, Object[] params, Integer pageSize, Integer pageNumber) {
long totalCount = this.countBySQL(hql, params);
return this.getPaginationBySQL(hql, params, pageSize, pageNumber, totalCount);
}
@Override
public Pagination listEntityByHQL1(String hql, Object[] params, Integer pageSize, Integer pageNumber) {
String nhql = "select count(*) from (select distinct ij.docserialnum,ir.docname,ir.scanuser,ir.orgcode,ir.cartonno,ir.boxno,to_char(ir.scantime, 'yyyy-mm-dd hh24:mi:ss'),count(ir.docname) " + hql.substring((hql.split("from")[0].length()-1)<0?0:(hql.split("from")[0].length()-1), hql.length()-1).split(" order by")[0]+")";
Integer totalCount = Integer.parseInt(this.queryObject1(nhql, params).toString());
return this.getPagination1(hql, params, pageSize, pageNumber, totalCount);
}
@Override
public Pagination listEntityByHQLbox(String hql, Object[] params, Integer pageSize, Integer pageNumber) {
String nhql = "select count(*) from (select distinct ij.docserialnum,to_char(ij.creationtime, 'yyyy-mm-dd hh24:mi:ss'),ij.maindocname,ir.scanuser,ir.orgcode,ir.cartonno,ir.boxno,count(ir.docname) " + hql.substring((hql.split("from")[0].length()-1)<0?0:(hql.split("from")[0].length()-1), hql.length()-1).split(" order by")[0]+")";
Integer totalCount = Integer.parseInt(this.queryObject1(nhql, params).toString());
return this.getPagination1(hql, params, pageSize, pageNumber, totalCount);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public Object queryObject1(final String hql, final Object[] params) {
Object obj = this.hibernateTemplate.execute(new HibernateCallback() {
@Override
public Object doInHibernate(Session session) throws HibernateException {
Query query = session.createSQLQuery(hql);
if (params != null) {
for (int i = 0; i < params.length; i++) {
query.setParameter(i, params[i]);
}
}
return query.uniqueResult();
}
});
return obj;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public Pagination getPagination1(final String hql, final Object[] params, final Integer pageSize, final Integer pageNumber, final Integer totalCount) {
return (Pagination) this.hibernateTemplate.execute(new HibernateCallback() {
@Override
public Object doInHibernate(Session session) throws HibernateException {
Pagination pagination = new Pagination(pageSize, pageNumber, totalCount);
Query query = session.createSQLQuery(hql);
if (params != null) {
for (int i = 0; i < params.length; i++) {
query.setParameter(i, params[i]);
}
}
query.setFirstResult(pageSize * (pageNumber - 1));
query.setMaxResults(pageSize);
pagination.setList(query.list());
return pagination;
}
});
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private Integer updateEntity(final String hql, final Object[] params) {
Integer i = (Integer) this.hibernateTemplate.execute(new HibernateCallback() {
@Override
public Object doInHibernate(Session session) throws HibernateException {
Query query = session.createQuery(hql);
if (params != null) {
for (int i = 0; i < params.length; i++) {
query.setParameter(i, params[i]);
}
}
Integer count = query.executeUpdate();
return count;
}
});
return i;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private Integer updateEntityBySQL(final String sql, final Object[] params) {
Integer i = (Integer) this.hibernateTemplate.execute(new HibernateCallback() {
@Override
public Object doInHibernate(Session session) throws HibernateException {
Query query = session.createSQLQuery(sql);
if (params != null) {
for (int i = 0; i < params.length; i++) {
query.setParameter(i, params[i]);
}
}
Integer count = query.executeUpdate();
return count;
}
});
return i;
}
@Override
public Integer updateByHQL(String hql, Object[] params) {
return updateEntity(hql, params);
}
@Override
public Integer updateBySQL(String sql, Object[] params) {
return updateEntityBySQL(sql, params);
}
@SuppressWarnings("unchecked")
@Override
public List<Object[]> listEntityBySelect(String hql, Object[] params) {
return (List<Object[]>) this.hibernateTemplate.find(hql, params);
}
@Override
public List<ComboBox> listFieldByHQL(String hql, Object[] params) {
@SuppressWarnings("unchecked")
List<String> objects = (List<String>) hibernateTemplate.find(hql, params);
List<ComboBox> lists = new ArrayList<ComboBox>();
for (String obj: objects) {
ComboBox cb = new ComboBox();
cb.setText(obj);
cb.setValue(obj);
lists.add(cb);
}
return lists;
}
@SuppressWarnings("rawtypes")
@Override
public List listEntityBySql(String sql, Class c) {
SQLQuery query=hibernateTemplate.getSessionFactory().getCurrentSession().createSQLQuery(sql).addEntity(c);
return query.list();
}
@Override
public void run()
{
while (true)
{
try
{
Thread.sleep(1000 * getRollingInterval());
}
catch (InterruptedException e)
{
e.printStackTrace();
}
String now = new SimpleDateFormat("yyyyMMddHHmm").format(new Date());
if (!now.equals(time)){
lock.writeLock().lock();
time = now;
value.set(getInitial());
lock.writeLock().unlock();
}
}
}
@Override
public String next()
{
lock.readLock().lock();
int index = value.getAndIncrement();
if(index==999999999)
{
value.set(0);
}
String num = String.valueOf(index);
time = String.valueOf(System.currentTimeMillis());
StringBuilder number = new StringBuilder();
int maxLength = 9;
if(num.length()<maxLength)
{
for(int i=0;i<(maxLength-num.length());i++)
{
number.append("0");
}
}
number.append(num);
StringBuffer sb = new StringBuffer(getPrefix()).append(getSplitString()).append(time).append(getSplitString()).append(number.toString());
lock.readLock().unlock();
return sb.toString();
}
}
每個dao大體情況:
@Repository("XXXDao")
public class XXXDaoHibernate extends GenericDaoHibernate<XXX(這個是實體), String> implements
XXXDao {
//這裡有需要就重寫next(),沒需要直接在service層用XXXDao.next()呼叫拿到主鍵
}