1. 程式人生 > >泛型方法應用場景

泛型方法應用場景

非泛型類能用泛型方法

public static <T> void synInfoForTable(Class<T> clazz, List<T>){}

其中T是不能呼叫任何方法的,想要T的型別,只能傳Class<T> clazz。

那麼這個T怎麼用呢?你就把T認為是一個返回型別:

比如在方法中

List<T> tblInfoListFromDB = new LinkedList<T>(query.list());

for (T tblInfoAPI : tblInfoListFromAPI) {}

就是對T的使用。

下面例子是一個同步案例:

/**
* 將資訊更新到資料庫(同步)

* @param clazz
*            實體類對應的class
* @param compareField
*            從API獲取的物件與資料庫中的物件要比較的欄位,首字母大寫,只能比較字串
* @param primaryKeyField
*            實體物件的主鍵欄位,首字母大寫
* @param primaryKeyClass
*            主鍵欄位對應的class
* @param tblInfoListFromAPI
*            從API獲取的物件集合
* @throws H3cException
*/

public static <T> void synInfoForTable(Class<T> clazz, String compareField, String primaryKeyField,
Class<?> primaryKeyClass, List<T> tblInfoListFromAPI, Integer cloudSign, String... userId)
throws Exception {
Session session = HBUtil.openNewSession();
Transaction t = null;
try {
t = session.beginTransaction();
StringBuilder hql = new StringBuilder("from ");
hql.append(clazz.getSimpleName());
hql.append(" where cloudId IS NOT NULL AND deleted = :deleted AND cloudSign = :cloudSign");
if (userId.length > 0) {// 如果要根據使用者同步,那麼在查詢時先查詢出該使用者的資源
hql.append(" AND userId = :userId");
}
Query query = session.createQuery(hql.toString());
query.setInteger("deleted", 0);// 只取未刪除的
query.setInteger("cloudSign", cloudSign);
if (userId.length > 0) {
query.setString("userId", userId[0]);
}


@SuppressWarnings("unchecked")
List<T> tblInfoListFromDB = new LinkedList<T>(query.list());
Method compareMethod = clazz.getMethod("get" + compareField);
Method getPrimaryKeyMethod = clazz.getMethod("get" + primaryKeyField);
Method setPrimaryKeyMethod = clazz.getMethod("set" + primaryKeyField, primaryKeyClass);
for (T tblInfoAPI : tblInfoListFromAPI) {// 使用增強迴圈
boolean flag = true;
String compareAPI = (String) compareMethod.invoke(tblInfoAPI);
for (T tblInfoDB : tblInfoListFromDB) {
String compareDB = (String) compareMethod.invoke(tblInfoDB);
if (compareAPI.equals(compareDB)) { // db方後面的原因是可能為空
if (!tblInfoAPI.equals(tblInfoDB)) {// 如果物件有變化,就要更新,否則不更新
// 為了防止主鍵被置為空,所以最後還要將原先的主鍵值保留下來,並賦值回去
// 這步如果之前已經賦值過,就沒必要做了
Object primaryKeyValue = getPrimaryKeyMethod.invoke(tblInfoDB);
CopyIgnoreProperty.copy(tblInfoAPI, tblInfoDB);
if (getPrimaryKeyMethod.invoke(tblInfoDB) == null) {
setPrimaryKeyMethod.invoke(tblInfoDB, primaryKeyValue);
}
session.update(tblInfoDB);
}
// 從集合中移除存在,是為了下面移除不存在的
tblInfoListFromDB.remove(tblInfoDB);
flag = false;
break;
}
}
if (flag) {// true為api新增的
// 如果主鍵是String型別(不會自動增長)的,且如果沒有被賦值,那麼就給他賦值
// 字串,36長度的
if ((getPrimaryKeyMethod.invoke(tblInfoAPI) == null) && (primaryKeyClass == String.class)) {
setPrimaryKeyMethod.invoke(tblInfoAPI, UUIDHexUtil.generate36bit());
}
session.save(tblInfoAPI);
}
}
// 因為前面tblVmInfoListFromDB已經把存在的都移除了,剩下的都是不存在了的
for (T tblInfoDB : tblInfoListFromDB) {
session.delete(tblInfoDB);
}
// 只要commit沒有執行,就不會儲存資料
t.commit();
} catch (Exception e) {
if (t != null) {
t.rollback();
}
throw new Exception("資料庫同步異常:" + e.getMessage(), e);// 呼叫者會說明是什麼異常
} finally {
session.close();
}