Java实现客户端下载服务器端的数据到sqlite数据库

        客户端获取数据时都从服务器上获取,速度会比较慢,所以可以将需要的服务器数据存放到客户端的sqlite数据库中,提高性能。主要的步骤为: “客户端向服务器端请求下载需要的数据”、“服务器端访问数据库,返回数据给客户端”、“客户端解析服务器返回的数据”、“客户端将对应数据库表中的数据全部清空”、“客户端将服务器端返回的数据插入到本地数据库”、“分页下载服务器端的数据”。

1、客户端向服务器端请求下载需要的数据。

Brand brand = new Brand();
brand.setPageIndex(BaseHttpBO.FIRST_PAGE_Index_Default);
brand.setPageSize(BaseHttpBO.PAGE_SIZE_LoadAll);
retrieveNCBaseModel(brand, brandHttpBO, brandSQLiteEvent, isPostDetail);

@Override
protected boolean doRetrieveNAsyncC(int iUseCaseID, BaseModel bm) {
    log.info("正在执行BrandHttpBO的retrieveNAsyncC,bm=" +(bm == null ? null : bm.toString()));

    RequestBody body = new FormBody.Builder()
            .build();
    Request req = new Request.Builder()
            .url(Configuration.HTTP_IP + Brand.HTTP_BRAND_RetrieveNC + bm.getPageIndex() + Brand.HTTP_BRAND_RETRIEVENC_PageSize + bm.getPageSize())
            .addHeader(BaseHttpBO.COOKIE, GlobalController.getInstance().getSessionID())
            .post(body)
            .build();
    HttpRequestUnit hru = new RetrieveNBrandC();
    hru.setRequest(req);
    hru.setTimeout(TIME_OUT);
    hru.setbPostEventToUI(true);
    httpEvent.setEventProcessed(false);
    httpEvent.setStatus(BaseEvent.EnumEventStatus.EES_Http_ToDo);
    hru.setEvent(httpEvent);
    HttpRequestManager.getCache(HttpRequestManager.EnumDomainType.EDT_Communication).pushHttpRequest(hru);

    log.info("正在发送RN到服务器....");

    return true;
}

2、服务器端访问数据库,返回数据给客户端。

		DataSourceContextHolder.setDbName(company.getDbName());
		List<?> ls = brandBO.retrieveNObject(getStaffFromSession(session).getID(), BaseBO.INVALID_CASE_ID, brand);

		logger.info("retrieveAll Brands error code=" + brandBO.getLastErrorCode());

		Map<String, Object> params = getDefaultParamToReturn(true);
		switch (brandBO.getLastErrorCode()) {
		case EC_NoError:
			for (Object obj : ls) {
				BaseModel bm = (BaseModel) obj;
				bm.setSyncDatetime(new Date());
			}

			params.put("brandList", ls);
			params.put("count", brandBO.getTotalRecord());
			params.put("msg", "");
			params.put("code", "0");
	params.put(BaseAction.JSON_ERROR_KEY, EnumErrorCode.EC_NoError.toString());

 调用存储过程,主要sql语句:

		SET iPageIndex = iPageIndex - 1;
		
		SET recordIndex = iPageIndex * iPageSize;
		
		SELECT F_ID, F_Name 
		FROM t_brand
		WHERE 1 = 1
		AND (CASE sName WHEN '' THEN 1=1 ELSE F_Name LIKE CONCAT('%',sName,'%') END)
		ORDER BY F_ID DESC
		LIMIT recordIndex, iPageSize;
		
		SELECT count(1) into iTotalRecord
		FROM t_brand
		WHERE 1 = 1
		AND (CASE sName WHEN '' THEN 1=1 ELSE F_Name LIKE CONCAT('%',sName,'%') END);
		SET iErrorCode := 0;
		SET sErrorMsg := '';

3、客户端解析服务器返回的数据。

JSONObject jsonObject = parseError(getResponseData());
if (jsonObject == null || getLastErrorCode() == ErrorInfo.EnumErrorCode.EC_DuplicatedSession) {
    break;
}

将jsonObject转为Java对象:

JSONArray jaStaff = jsonObject.getJSONArray(BaseModel.JSON_OBJECTLIST_KEY);
List<BaseModel> brandList = new Brand().parseN(jaStaff);

4、客户端将对应数据库表中的数据全部清空。

@Override
    protected boolean refreshByServerDataAsyncC(final int iUseCaseID, final List<?> bmNewList, final BaseSQLiteEvent event) {
        log.info("正在进行BrandPresenter的refreshByServerDataAsyncC,bmNewList=" + (bmNewList == null ? null : bmNewList.toString()));

        switch (iUseCaseID) {
            default:
                TaskScheduler.execute(new Runnable() {
                    @Override
                    public void run() {
                        log.info("已经得到服务器返回的需要同步的Brand数据, 准备进行同步...");

//                        event.setEventTypeSQLite(BaseSQLiteEvent.EnumSQLiteEventType.ESET_Brand_RefreshByServerDataAsync_Done);
                        event.setLastErrorCode(ErrorInfo.EnumErrorCode.EC_NoError);
                        //删除本地所有的数据
                        deleteNSync(iUseCaseID, null);
                        if (getLastErrorCode() == ErrorInfo.EnumErrorCode.EC_NoError) {
                            //同步所有服务器返回的数据
                            createNSync(iUseCaseID, bmNewList);
                            if (getLastErrorCode() != ErrorInfo.EnumErrorCode.EC_NoError) {
                                event.setLastErrorCode(ErrorInfo.EnumErrorCode.EC_OtherError);
                            }
                        } else {
                            event.setLastErrorCode(ErrorInfo.EnumErrorCode.EC_OtherError);
                        }
//                        event.setLastErrorCode(ErrorInfo.EnumErrorCode.EC_NoError);
                        event.setStatus(BaseEvent.EnumEventStatus.EES_SQLite_DoneApplyServerData);
                        //
                        EventBus.getDefault().post(event);
                    }
                });
                break;
        }
        return true;
    }

deleteNSync,清空数据库表brand中的数据:

@Override
protected BaseModel deleteNSync(int iUserCaseID, BaseModel bm) {
    log.info("正在进行BrandPresenter的deleteNSync,bm=" + (bm == null ? null : bm.toString()));

    try {
        dao.getBrandDao().deleteAll();
        lastErrorCode = ErrorInfo.EnumErrorCode.EC_NoError;
    } catch (Exception e) {
        log.info("执行deleteNSync失败,错误信息为" + e.getMessage());

        e.printStackTrace();
        lastErrorCode = ErrorInfo.EnumErrorCode.EC_OtherError;
    }

    return null;
}

5、客户端将服务器端返回的数据插入到本地数据库。

createNSync,向数据库表brand插入N条数据:

@Override
protected List<BaseModel> createNSync(int iUseCaseID, final List<?> list) {
    log.info("正在进行BrandPresenter的createNSync,list=" + (list == null ? null : list.toString()));

    switch (iUseCaseID) {
        default:
            try {
                for (int i = 0; i < list.size(); i++) {
                    long id = dao.getBrandDao().insert((Brand) list.get(i));
                    ((Brand) list.get(i)).setID(id);
                    lastErrorCode = ErrorInfo.EnumErrorCode.EC_NoError;
                }
            } catch (Exception e) {
                log.info("执行createNSync时出现异常,错误信息:" + e.getMessage());
                e.printStackTrace();
                lastErrorCode = ErrorInfo.EnumErrorCode.EC_OtherError;
            }
            return (List<BaseModel>) list;
    }
}

6、分页下载服务器端的数据。

对于数据量比较大的数据,采用分页下载。

设置pageSize为50,每页下载50条疏忽。pageIndex为start,标记为请求第一页:

Commodity commodity = new Commodity();
commodity.setPageIndex(BaseHttpBO.FIRST_PAGE_Index_Default);
commodity.setPageSize(BaseHttpBO.PAGE_SIZE_LoadPageByPage);
commoditySQLiteBO.getSqLiteEvent().setPageIndex(Commodity.PAGEINDEX_START);//...
retrieveNCBaseModel(commodity, commodityHttpBO, commoditySQLiteEvent, isPostDetail);

获取服务器返回的总记录数count,算出一共有totalPageIndex页,记录当前已经下载的页数runTimes,如果已经下载完成,则标记pageIndex为end:

if (baseHttpBO.getHttpEvent().getCount() != null && !"".equals(baseHttpBO.getHttpEvent().getCount())) {
    count = Integer.valueOf(baseHttpBO.getHttpEvent().getCount());
    int totalPageIndex = count % Integer.valueOf(bm.getPageSize()) != 0 ? count / Integer.valueOf(bm.getPageSize()) + 1 : count / Integer.valueOf(bm.getPageSize());//查询条形码需要totalPageIndex页才能查完

    if (runTimes < totalPageIndex) {
        bm.setPageIndex(String.valueOf(++runTimes));
        // 判断是否为Commodity并且是页数中的最后一页。(为了在present中删除并更新掉z最后一页的所有数据)
        if (bm instanceof Commodity && bm.getPageIndex().equals(String.valueOf(totalPageIndex))) {
            commoditySQLiteBO.getSqLiteEvent().setPageIndex(Commodity.PAGEINDEX_END);
        } else if (bm instanceof Barcodes && bm.getPageIndex().equals(String.valueOf(totalPageIndex))) {
            barcodesSQLiteBO.getSqLiteEvent().setPageIndex(Barcodes.PAGEINDEX_END);
        }
    } else {
        break;
    }
} 

如果是下载第一页数据pageIndex为start,那么找出服务器返回的数据中最小的ID,将小于最小ID的数据全部删除掉。

同理,如果下载的是最后一数据,pageIndex为end,那么需要找出服务器返回的数据中最大的ID,将大于最大ID的数据全部删除掉。

这样做的原因是防止sqlite数据库有残留数据,不在最小ID和最大ID之间的数据应是残留数据:

if (event.getPageIndex() != null && event.getPageIndex().equals(Commodity.PAGEINDEX_START)) {
    String sql = "delete from " + getTableName() + " where F_ID > ? ";//
    String[] conditions = new String[]{String.valueOf(commodityList.get(0).getID())};
    dao.getDatabase().execSQL(sql, conditions);
} else if (event.getPageIndex() != null && event.getPageIndex().equals(Commodity.PAGEINDEX_END)) {
    String sql = "delete from " + getTableName() + " where F_ID < ? ";
    String[] conditions = new String[]{String.valueOf(commodityList.get(commodityList.size() - 1).getID())};
    dao.getDatabase().execSQL(sql, conditions);
}

如果是下载的页数数第一页和最后一页之间,则找出服务器返回的数据中的最大ID和最小ID,删除sqlite数据库中大于最小ID和小于最大ID之间的数据,然后插入新的数据即可:

event.setPageIndex(""); //初始化分页标记
String sql = "delete from " + getTableName() + " where F_ID >= ? and F_ID <= ?";
String[] conditions = new String[]{String.valueOf(commodityList.get(commodityList.size() - 1).getID()), String.valueOf(commodityList.get(0).getID())};

//先删除本地数据库原有的数据
dao.getDatabase().execSQL(sql, conditions);
// 删除从表
for(Commodity commodity : commodityList) {
    String sqlCommShopInfo = "delete from " + dao.getCommodityShopInfoDao().getTablename() + " where F_CommodityID = ? ";//
    String[] conditionsCommShopInfo = new String[]{String.valueOf(commodity.getID())};
    dao.getDatabase().execSQL(sqlCommShopInfo, conditionsCommShopInfo);
}

for (int i = 0; i < commodityList.size(); i++) {
    dao.getCommodityDao().insert((Commodity) commodityList.get(i));
    List<CommodityShopInfo> commodityShopInfoList = (List<CommodityShopInfo>) commodityList.get(i).getListSlave2();
    for(CommodityShopInfo commodityShopInfo : commodityShopInfoList) {
        if(commodityShopInfo.getID() != null && commodityShopInfo.getID().intValue() > 0 && dao.getCommodityShopInfoDao().load(commodityShopInfo.getID()) != null) {
            dao.getCommodityShopInfoDao().deleteByKey(commodityShopInfo.getID());
        }
        dao.getCommodityShopInfoDao().insert(commodityShopInfo);
    }
}
posted @ 2021-12-22 09:25  Boxin-kim  阅读(142)  评论(0)    收藏  举报
Web Analytics
Guang Zhou Boxin