因项目需要做了一个将DB数据产生为json文件的小工具,该工具是基于mybatis的配置查询数据,然后产生json数据文件。
mybatis配置:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-/mybatis.org/DTD Config 3.0/EN"
"http:/mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url"
value="jdbc:mysql:/localhost:3306/ibatis?useUnicode=true&characterEncoding=UTF-8" />
<property name="username" value="root" />
<property name="password" value="coship" />
</dataSource>
</environment>
</environments>
<mappers>
<mapper url="file:./UserMapper.xml" />
<!-- <mapper url="file:///E:/develop/workspace/com/src/main/resources/ibatis/OrderMapper.xml" />
<mapper url="file:///E:/develop/workspace/com/src/main/resources/ibatis/UserTypeMapper.xml" /> -->
</mappers>
</configuration>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ibatis.test.model.UserMapper"> <!--mybatis的namespace是必须的 -->
<select id="queryUsersByTypeID" parameterType="java.util.Map" resultType="java.util.Map"> <!--resultType使用的是简称 -->
SELECT *
FROM ibatis.User
WHERE typeId = #{id}
</select>
</mapper>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ibatis.test.model.UserTypeMapper"> <!--mybatis的namespace是必须的 -->
<select id="queryTypes" parameterType="java.util.Map"
resultType="java.util.Map"> <!--resultType使用的是简称 -->
SELECT *
FROM ibatis.User_Type
limit ${start},${limit}
</select>
</mapper>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ibatis.test.model.OrderMapper"> <!--mybatis的namespace是必须的 -->
<select id="queryOrdersByUserId" parameterType="java.util.Map" resultType="java.util.Map"> <!--resultType使用的是简称 -->
SELECT *
FROM ibatis.Order
WHERE userId = #{id}
</select>
</mapper>
<?xml version="1.0" encoding="UTF-8"?>
<queries>
<query selectId="com.ibatis.test.model.UserTypeMapper.queryTypes"
fileName="queryUsers" primaryID="id" fileRecrod="5" dataName="data">
<collection selectId="com.ibatis.test.model.UserMapper.queryUsersByTypeID"
fileName="users" primaryID="id" parentFkName="id" included="false"
dataName="users" fileRecrod="1">
<collection selectId="com.ibatis.test.model.OrderMapper.queryOrdersByUserId"
fileName="order" parentFkName="id" included="false" dataName="order"
primaryID="id" fileRecrod="1">
</collection>
</collection>
</query>
</queries>
上面是自己产生json文件的配置,每个查询(query)产生一个文件,里面的collection可单独产生文件或一起产生到外面的query中,里面的collection需要外面传递参数进去查询,参数字段parentFkName,属性说明在下面:
/* 查询id */
public static final String C_SELECT_ID = "selectId";
public static final String C_FILE_NAME = "fileName";// 文件的名字
public static final String C_DATA_NAME = "dataName";// query节点:数据项名,collection节点:如果collection一起产生到上一层的查询中对应的数据名字,否则就为自己的数据名
public static final String C_PARENT_FK_NAME = "parentFkName";// 父层参数
public static final String C_PRIMARY_ID = "primaryID";// 父层的主键id,如果collection不和父层到一个文件,将以父层作为文件名的一部分
public static final String C_MAX_RECORDS = "maxRecords";// 最大记录数,限制记录,此时需要配置mybatis查询时现在记录
public static final String C_PER_RECORD_TO_FILE = "fileRecrod";// 每个文件中产生的记录数,如果为0,所有的记录写到一个文件中,为1,单条记录产生一个文件,名字为fileName+primaryID的值+.json,如果>1,分页产生文件,fileName+页码
public static final String C_INCLUDED = "included";// collection标识是否和父层生成到同一个文件中
// json数据记录名
public static final String C_DATA_JSON_NAME = "dataList";// 默认的数据项名
package com.ibatis.test.parser;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ibatis.test.constants.PubConstant;
import com.ibatis.test.vo.BusinessConfig;
import com.ibatis.test.vo.IPublish;
import com.ibatis.test.vo.Query;
import com.ibatis.test.vo.impl.Publish;
public class PubParser {
private String confFilePath;
private static Logger logger = LoggerFactory.getLogger(PubParser.class);
public PubParser() {
}
public PubParser(String confFilePath) {
this.confFilePath = confFilePath;
}
private Document init() throws IOException, DocumentException {
if (this.confFilePath == null || "".equals(this.confFilePath.trim()))
throw new IllegalArgumentException("未设置后台配置文件的路径");
SAXReader saxReader = new SAXReader();
Reader r = new InputStreamReader(new FileInputStream(this.confFilePath));
Document document = saxReader.read(r);
return document;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public void parseXml(BusinessConfig bsConfig, String businessCode)
throws Exception {
try {
// 获取xml document
Document document = init();
List list = document.selectNodes("//queries");
if (list.size() > 1) {
throw new Exception(
"配置文件有误,包含多个<queries>节点,多个查询请配置在<queries>节点中");
}
if (list.size() == 1) {
List<Element> queryList = document
.selectNodes("//queries/query");
if (queryList.size() > 0) {
for (int i = 0; i < queryList.size(); i++) {
Query query = new Query();
Element e = queryList.get(i);
IPublish root = parsePublish(e, null);
query.setRoot(root);
bsConfig.addQuery(query);
}
}
}
} catch (Exception ex) {
logger.error("解析xml发生错误", ex);
throw ex;
}
}
/**
* 解析子的节点
*/
@SuppressWarnings("unchecked")
private void parseSubPublishes(Element e, IPublish parent) throws Exception {
// 解析collection节点
List<Element> collectionList = e.elements("collection");
for (int i = 0; i < collectionList.size(); i++) {
Element collection = collectionList.get(i);
parsePublish(collection, parent);
}
}
private IPublish parsePublish(Element collection, IPublish parent)
throws Exception {
Map<String, String> paramMap = parseAttributeMap(collection);
// 得到对应的ibatis查询id
String selectId = paramMap.get(PubConstant.C_SELECT_ID);
if (StringUtils.isBlank(selectId))
throw new Exception("配置格式有误,未配置(" + PubConstant.C_SELECT_ID
+ ")ibatis查询ID");
IPublish publish = new Publish(selectId, parent);
parsePublishAttributes(paramMap, publish);
// 解析子节点
parseSubPublishes(collection, publish);
return publish;
}
private void parsePublishAttributes(Map<String, String> paramMap,
IPublish publish) throws Exception {
// 得到对应的ibatis查询id
String selectId = paramMap.get(PubConstant.C_SELECT_ID);
// 得到文件名称
String fileName = paramMap.get(PubConstant.C_FILE_NAME);
// 得到数据节点名称
String dataName = paramMap.get(PubConstant.C_DATA_NAME);
// 得到是否单独生成一个文件标志
String included = paramMap.get(PubConstant.C_INCLUDED);
// 得到配置的最大记录数
String maxRecords = paramMap.get(PubConstant.C_MAX_RECORDS);
// 得到是否每条记录都生成一个文件
String isPrcdFile = paramMap.get(PubConstant.C_PER_RECORD_TO_FILE);
String parentFKName = paramMap.get(PubConstant.C_PARENT_FK_NAME);
String primaryId = paramMap.get(PubConstant.C_PRIMARY_ID);
if (StringUtils.isBlank(primaryId))
throw new Exception("配置格式有误,未配置(" + PubConstant.C_PRIMARY_ID
+ ")主键ID名称");
if (included == null || "".equals(included.trim())) {
// 默认为和上级生成在同一个目录下
included = "1";
} else {
included = included.trim();
if ("true".equals(included)) {
included = "1";
} else if ("false".equals(included)) {
included = "0";
} else {
throw new Exception("配置格式有误,collection(" + fileName + ")"
+ PubConstant.C_INCLUDED + "属性配置不正确,正确配置为(true/false)");
}
}
if (publish.isRoot()) {
if (fileName == null || "".equals(fileName.trim()))
throw new Exception("配置格式有误,未配置name属性");
} else {
if ("0".equals(included)) {
if (fileName == null || "".equals(fileName.trim()))
throw new Exception("配置格式有误,collection[" + selectId
+ "]配置为单独生成文件,就需要配置fileName属性(文件的名称前缀)");
}
}
if (!publish.isRoot()) {
if (StringUtils.isBlank(parentFKName)) {
throw new Exception("配置格式有误,collect[" + selectId + "]必须配置"
+ PubConstant.C_PARENT_FK_NAME + "属性值");
}
}
// 默认json名字
if (StringUtils.isBlank(dataName)) {
dataName = PubConstant.C_DATA_JSON_NAME;
}
if ("0".equals(included)) {
// 去首尾/
fileName = replaceAllSeg(fileName, "/");
if (fileName.indexOf("\\") > -1) {
throw new Exception("配置格式有误,collection(" + fileName
+ ")name属性配置不正确,请使用/作为分隔符");
}
if (fileName.indexOf("/") > -1) {
throw new Exception("配置格式有误,collection(" + fileName
+ ")name属性配置不正确,属性included=false,name属性不能包含/或\\");
}
}
if (isPrcdFile != null) {
try {
int tmp = Integer.parseInt(isPrcdFile.trim());
if (tmp < 0) {
throw new Exception("配置格式有误,"
+ PubConstant.C_PER_RECORD_TO_FILE + "必须为正整数!");
}
} catch (Exception ex) {
throw new Exception("配置格式有误,"
+ PubConstant.C_PER_RECORD_TO_FILE + "必须为正整数!");
}
} else {
isPrcdFile = "0";
}
if (maxRecords != null) {
try {
int tmp = Integer.parseInt(maxRecords);
if (tmp < 0) {
throw new Exception("配置格式有误,最大记录数必须为整数");
}
} catch (Exception ex) {
throw new Exception("配置格式有误,最大记录数必须为整数");
}
}
publish.addParameter(PubConstant.C_INCLUDED, included);
publish.addParameter(PubConstant.C_FILE_NAME, fileName);
publish.addParameter(PubConstant.C_DATA_NAME, dataName);
publish.addParameter(PubConstant.C_MAX_RECORDS, maxRecords);
publish.addParameter(PubConstant.C_PER_RECORD_TO_FILE,
isPrcdFile.trim());
publish.addParameter(PubConstant.C_INCLUDED, included);
publish.addParameter(PubConstant.C_PRIMARY_ID, primaryId);
publish.addParameter(PubConstant.C_PARENT_FK_NAME, parentFKName);
}
@SuppressWarnings("unchecked")
private Map<String, String> parseAttributeMap(Element e) {
Map<String, String> map = new HashMap<String, String>();
Iterator<Attribute> iterator = e.attributeIterator();
while (iterator.hasNext()) {
Attribute attr = iterator.next();
map.put(attr.getName(), attr.getData().toString());
}
return map;
}
private String replaceAllSeg(String inStr, String strSeg) {
String tmp = inStr;
if (inStr == null)
return null;
while (tmp.startsWith(strSeg)) {
tmp = tmp.substring(1);
}
while (tmp.endsWith(strSeg)) {
tmp = tmp.substring(0, tmp.length() - 1);
}
return tmp;
}
public void setConfFilePath(String confFilePath) {
this.confFilePath = confFilePath;
}
public static void main(String[] args) {
// 业务端配置文件解析器
PubParser parse = new PubParser(
"E:\\work\\project2\\vasms-pub\\src\\main\\resources\\com\\coship\\vasms\\pub\\server.xml");
BusinessConfig bsConfig = new BusinessConfig("test");
try {
parse.parseXml(bsConfig, "test");
} catch (Exception e) {
e.printStackTrace();
}
}
}
下面贴出数据发布类
package com.ibatis.test.exec;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ibatis.test.constants.PubConstant;
import com.ibatis.test.dao.BaseDAO;
import com.ibatis.test.dao.impl.BaseDAOImpl;
import com.ibatis.test.util.FileUtil;
import com.ibatis.test.util.FileWriterUtil;
import com.ibatis.test.vo.BusinessConfig;
import com.ibatis.test.vo.IPublish;
import com.ibatis.test.vo.Query;
import com.ibatis.test.vo.impl.Publish;
/**
*
*
* File Name : JobPubber.java
*
* @Description : 发布任务类
* @author 904941
*/
public class JobPubber implements Callable<Boolean> {
// 发布路径池管理锁
private static Lock lock = new ReentrantLock();
// 发布路径锁池
private final Map<String, LockNum> pathLocks = new HashMap<String, LockNum>();
private final BusinessConfig bsConfig;
private BaseDAO baseDao;
private final Logger logger = LoggerFactory.getLogger(JobPubber.class);
public JobPubber(BusinessConfig bsConfig) throws IOException {
this.bsConfig = bsConfig;
baseDao = new BaseDAOImpl(FileUtil.joinTwoDir(bsConfig.getBasePath(),
PubConstant.C_SQL_MAP_CONFIG_FILE));
}
public Boolean call() throws Exception {
IPublish exceptionPub = null;
try {
for (Query qc : bsConfig.getQueries()) {
exceptionPub = qc.getRoot();
// 检查这个query每页生成多少条记录
// isPrcdFile=0:所有记录生成到一个文件中 文件命名:配置的name属性+".js"
// isPrcdFile=1:一条记录生成到一个文件中 文件命名:配置的name属性+"_"+"主键值"+".js"
// isPrcdFile>1:siPrcdFile条记录生成到一个文件中
// 文件命名:配置的name属性+"_"+"当前的页码"+".js"
String isPrcdFile = (String) qc.getRoot().getParameter(
PubConstant.C_PER_RECORD_TO_FILE);
if (isPrcdFile.trim().equals("0")) {
// 所有记录写到一个文件中
writeAllRecordsFile(qc.getRoot(), null, null);
} else if (isPrcdFile.trim().equals("1")) {
// 每条记录都产生一个文件
writeOneRecordFile(qc.getRoot(), null, null);
} else {
// 全部(<maxrecords)记录产生分页文件
writePageRecordFile(qc.getRoot(), null, null);
}
}
LockNum lockNum = getLock(bsConfig.getJsonFilePath());
try {
lockNum.lock.lock();
lockNum.num++;
FileUtil.move(bsConfig.getJsonTempFilePath(),
bsConfig.getJsonFilePath());
} finally {
lockNum.num--;
if (lockNum.num == 0) {
removeLock(lockNum);
}
lockNum.lock.unlock();
}
return new Boolean(true);
} catch (Exception ex) {
FileUtil.deleteDir(bsConfig.getJsonTempFilePath());
// 清理发生异常时的缓存
// if (this.jobsRunner != null)
// this.jobsRunner.addException(bsConfig.getBusinessCode()
// + exceptionPub.getSelectId(), "发布发生错误");
logger.error("业务编码为:" + bsConfig.getBusinessCode() + "的业务发布发生错误",
ex);
return new Boolean(false);
} finally {
// 删除临时目录---- 改用创建临时目录的方式后就不需要创建临时文件,删除文件比拷贝文件性能高,这样可提高性能,
FileUtil.deleteDir(bsConfig.getJsonTempFilePath());
}
}
/**
*
* 一条记录产生为一个文件
*
* @param pub
* 一个类似collection节点的配置
* @param primaryID
* 上层表的id值,格式为:id1,id1_id2,id1_id2_id3,id1_id2_id3_..._idn
* @throws Exception
*
*/
private void writeOneRecordFile(IPublish pub, Map<String, Object> paramMap,
String primaryID) throws Exception {
FileWriterUtil fu = new FileWriterUtil();
// 限制记录数
int maxRecords = getMaxRecords(pub);
int perPageRecords = maxRecords;
int currentPageNum = 1;
// 页码添加到文件名的后面 如 queryName_页码.js
if (paramMap == null)
paramMap = new HashMap<String, Object>();
String subbfixValue = StringUtils.isBlank(primaryID) ? "" : primaryID
+ "_";
try {
// 迭代查询数据
List<Map<String, Object>> datalist = null;
datalist = selectPageDataList(pub, paramMap, maxRecords,
currentPageNum, perPageRecords);
Map<String, Object> dataMap = new HashMap<String, Object>();
// 开始查询数据
if (datalist.size() > 0) {
// 处理子节点
dealCollections(pub, datalist, primaryID);
for (Map<String, Object> record : datalist) {
String[] primaryIds = ((String) pub
.getParameter(PubConstant.C_PRIMARY_ID)).split(",");
String value = "";
for (String str : primaryIds) {
if (!value.equals("")) {
value += "_";
}
value += record.get(str);
}
String fileName = createJsonFileName(pub, subbfixValue
+ value);
dataMap.put(
(String) pub.getParameter(PubConstant.C_DATA_NAME),
record);
writeFile(fu, JSONObject.fromObject(dataMap).toString(),
fileName);
}
}
} finally {
fu.close();
}
}
/**
*
* 多条记录分页写到一个文件中
*
* @param pub
* 一个类似collection节点的配置
* @param primaryID
* 上层表的id值,格式为:id1,id1_id2,id1_id2_id3,id1_id2_id3_..._idn
* @throws Exception
*
*/
private void writePageRecordFile(IPublish pub,
Map<String, Object> paramMap, String primaryID) throws Exception {
// 限制记录数
int maxRecords = getMaxRecords(pub);
// 当前正在写的文件页码
int currentPageNum = 1;
// 每页的记录数
int perPageRecords = Integer.parseInt((String) pub
.getParameter(PubConstant.C_PER_RECORD_TO_FILE));
// 总记录数
int total = 0;
// 写文件的工具类
FileWriterUtil fu = new FileWriterUtil();
// 页码添加到文件名的后面 如 queryName_页码.js
if (paramMap == null)
paramMap = new HashMap<String, Object>();
String subbfixValue = StringUtils.isBlank(primaryID) ? "" : primaryID
+ "_";
try {
// 迭代查询数据
checkPageSql(pub.getSelectId(), paramMap);
List<Map<String, Object>> datalist = null;
datalist = selectPageDataList(pub, paramMap, maxRecords,
currentPageNum, perPageRecords);
Map<String, Object> dataMap = new HashMap<String, Object>();
// 开始查询数据
while (datalist.size() > 0) {
total += datalist.size();
// 处理子节点
dealCollections(pub, datalist, primaryID);
dataMap.put((String) pub.getParameter(PubConstant.C_DATA_NAME),
datalist);
String fileName = createJsonFileName(pub,
subbfixValue + String.valueOf(currentPageNum));
writeFile(fu, JSONObject.fromObject(dataMap).toString(),
fileName);
currentPageNum++;
datalist = selectPageDataList(pub, paramMap, maxRecords,
currentPageNum, perPageRecords);
}
// 写分页文件
writePageFile(pub, perPageRecords, total, fu, primaryID);
} finally {
fu.close();
}
}
/**
*
* 写所有记录生成到同一个js文件 对应的方法为一条记录到一个js文件中
*
* @param pub
*
* @throws Exception
*
*/
private void writeAllRecordsFile(IPublish pub,
Map<String, Object> paramMap, String primaryID) throws Exception {
FileWriterUtil fu = new FileWriterUtil();
// 限制记录数
int maxRecords = getMaxRecords(pub);
int perPageRecords = maxRecords;
int currentPageNum = 1;
// 页码添加到文件名的后面 如 queryName_页码.js
if (paramMap == null)
paramMap = new HashMap<String, Object>();
String subbfixValue = StringUtils.isBlank(primaryID) ? "" : primaryID
+ "_";
try {
// 迭代查询数据
List<Map<String, Object>> datalist = null;
datalist = selectPageDataList(pub, paramMap, maxRecords,
currentPageNum, perPageRecords);
Map<String, Object> dataMap = new HashMap<String, Object>();
// 开始查询数据
if (datalist.size() > 0) {
// 处理子节点
dealCollections(pub, datalist, primaryID);
String fileName = createJsonFileName(pub, subbfixValue);
dataMap.put((String) pub.getParameter(PubConstant.C_DATA_NAME),
datalist);
writeFile(fu, JSONObject.fromObject(dataMap).toString(),
fileName);
}
} finally {
fu.close();
}
}
private List<Map<String, Object>> selectPageDataList(IPublish pub,
Map<String, Object> paramMap, int maxRecords, int currentPageNum,
int perPageRecords) {
List<Map<String, Object>> datalist;
bindPageParams(paramMap, maxRecords, currentPageNum, perPageRecords);
datalist = baseDao.selectList(pub.getSelectId(), paramMap);
return datalist;
}
private void writePageFile(IPublish pub, int perPageRecords, int total,
FileWriterUtil fu, String primaryID) throws IOException {
int pages = total / perPageRecords;
int pageResult = total % perPageRecords;
if (pageResult != 0) {
pages += 1;
}
String json = "{\"total\":\"" + total + "\",\"pages\":\"" + pages
+ "\"}";
String pageFileName = createJsonFileName(pub, "page"
+ (primaryID == null || "".equals(primaryID) ? "" : "_"
+ primaryID));
writeFile(fu, json, pageFileName);
}
private void writeFile(FileWriterUtil fu, String json, String fileName)
throws IOException {
try {
fu.init(fileName);
fu.writeFile(json);
} finally {
fu.close();
}
}
private void bindPageParams(Map<String, Object> dataMap, int maxRecords,
int currentPageNum, int perPageRecords) {
dataMap.put("start", getStart(currentPageNum, perPageRecords));
dataMap.put("limit",
getLimit(currentPageNum, perPageRecords, maxRecords));
}
private int getStart(int currentPageNum, int perPagerRecords) {
return (currentPageNum - 1) * perPagerRecords;
}
private int getLimit(int currentPageNum, int perPageRecords, int maxRecords) {
int end = currentPageNum * perPageRecords;
if (maxRecords > 0) {
return end > maxRecords ? maxRecords : end;
}
return end;
}
private int getMaxRecords(IPublish pub) {
String maxRecordsStr = (String) pub
.getParameter(PubConstant.C_MAX_RECORDS);
int maxRecords = 0;
if (maxRecordsStr != null)
maxRecords = Integer.parseInt(maxRecordsStr.trim());
return maxRecords;
}
private void checkPageSql(String selectId, Map<String, Object> paramMap)
throws Exception {
String sql = baseDao.getIbatisSql(selectId, paramMap);
if (sql != null && sql.indexOf("limit") < 0) {
throw new Exception("query:" + selectId
+ " 支持分页,但配置的sql语句没有包含limit子句,格式为:limit ${start},${limit}");
}
}
/**
*
* 处理collection节点,如果collection节点需要单独写到文件中,用所有记录写到一个文件,分页写进文件,
* 一条记录写到一个文件中的方法进行迭代
*
* @param pub
* 一个类似collection节点的配置
* @param primaryID
* 上层表的id值,格式为:id1,id1_id2,id1_id2_id3,id1_id2_id3_..._idn
* @param subDatalist
* 上层表的数据
* @param primaryKeyName
* 上层表的主键名 如果上层表是一条记录产生一个文件,则主键名可以直接传过来,否则为null
* @throws BusinessException
* @throws Exception
*
*/
private void dealCollections(IPublish pub,
List<Map<String, Object>> subDatalist, String primaryID)
throws Exception { // 上层表的主键名
String tmpPrimaryKeyName = null;
for (int c = 0; c < pub.getChildren().size(); c++) {
IPublish subPub = pub.getChildren().get(c);
// 得到主键名
if (c == 0 && tmpPrimaryKeyName == null)
tmpPrimaryKeyName = (String) subPub
.getParameter(PubConstant.C_PARENT_FK_NAME);
// 单独生成数据文件的collection的处理
for (int j = 0; j < subDatalist.size(); j++) {
Map<String, Object> dataMap = subDatalist.get(j);
Map<String, Object> paramMap = new HashMap<String, Object>();
paramMap.put(tmpPrimaryKeyName, dataMap.get(tmpPrimaryKeyName));
String nextPrimaryID = (primaryID == null
|| "".equals(primaryID) ? "" : primaryID + "_")
+ dataMap.get(tmpPrimaryKeyName);
if (Integer.parseInt((String) subPub
.getParameter(PubConstant.C_INCLUDED)) == 0) {
int pageRecords = Integer.parseInt((String) subPub
.getParameter(PubConstant.C_PER_RECORD_TO_FILE));
if (pageRecords == 0) {
// 所有数据生成到一个文件中
// 命名为:查询名称+"_"+前面传过来的主键值+".js"
writeAllRecordsFile(subPub, paramMap, nextPrimaryID);
} else if (pageRecords == 1) {
// 每条记录产生一个文件
writeOneRecordFile(subPub, paramMap, nextPrimaryID);
} else if (pageRecords > 1) {
// 产生分页记录
writePageRecordFile(subPub, paramMap, nextPrimaryID);
}
} else {
List<Map<String, Object>> datalist = getAllRecords(subPub,
dataMap, paramMap);
dealCollections(subPub, datalist, nextPrimaryID);
}
}
}
}
private List<Map<String, Object>> getAllRecords(IPublish subPub,
Map<String, Object> dataMap, Map<String, Object> paramMap) {
// 限制记录数
int maxRecords = getMaxRecords(subPub);
if (maxRecords > 0) {
paramMap.put("limit", maxRecords);
}
List<Map<String, Object>> datalist = baseDao.selectList(
subPub.getSelectId(), paramMap);
dataMap.put((String) subPub.getParameter(PubConstant.C_DATA_NAME),
datalist);
return datalist;
}
/**
*
* 创建文件的路径,所为collettion节点时,将上层查询的名字作为父目录
*
* @param pub
* @param subbfixValue
* @return
*
*/
private String createJsonFileName(IPublish pub, String subbfixValue) {
String jsonFileName = "";
jsonFileName += createJsonFileDir(pub);
if (subbfixValue != null && !"".equals(subbfixValue))
jsonFileName += "_";
jsonFileName += subbfixValue + PubConstant.C_FILE__SUFFIX;
return jsonFileName;
}
/**
*
* 创建json文件的路径 如果是collection,则将上层表的名字作为路径
*
* @param pub
* @return
*
*/
private String createJsonFileDir(IPublish pub) {
// 最上层表 直接在basePath创建数据文件
if (!pub.isRoot()) {
return FileUtil.joinTwoDir(createJsonFileDir(pub.getParent()),
(String) pub.getParameter(PubConstant.C_FILE_NAME));
}
// 不为上层表时,将上层表的名字作为路径的一部分
return FileUtil.joinTwoDir(bsConfig.getJsonTempFilePath(),
(String) pub.getParameter(PubConstant.C_FILE_NAME));
}
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append(bsConfig.getBusinessCode());
return sb.toString();
}
// 发布路径锁
class LockNum {
int num = 0;
String filePath;
Lock lock = new ReentrantLock();
LockNum(String filePath) {
this.filePath = filePath;
}
}
// 根据路径获取锁
private LockNum getLock(String filePath) {
try {
lock.lock();
LockNum result = pathLocks.get(filePath);
if (null == result) {
result = new LockNum(filePath);
}
pathLocks.put(filePath, result);
return result;
} finally {
lock.unlock();
}
}
// 删除锁
private void removeLock(LockNum lockNum) {
try {
lock.lock();
pathLocks.remove(lockNum.filePath);
} finally {
lock.unlock();
}
}
}
下面是利用mybatis做数据查询的类
package com.ibatis.test.dao.impl;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import com.ibatis.test.dao.BaseDAO;
public class BaseDAOImpl implements BaseDAO {
private Reader reader;
private SqlSessionFactory ssf;
private SqlSession sqlSession;
public BaseDAOImpl(String resource) throws IOException {
// reader = new FileReader(new File(resource));
// reader = Resources.getResourceAsReader(resource);
// reader = Resources.getResourceAsReader("ibatis\\sqlMapConfig.xml");
ssf = new SqlSessionFactoryBuilder().build(new FileReader(new File(
resource)));
sqlSession = ssf.openSession();
}
@SuppressWarnings("unchecked")
public List<Map<String, Object>> selectList(String selectId,
Map<String, Object> map) {
return (List<Map<String, Object>>) this.getSqlSession().selectList(
selectId, map);
}
/**
*
* @param id
* xml 中sql的id ,如 <select id="">中的""
* @param parameterObject
* 传给这条sql的参数
* @return
*/
public String getIbatisSql(String id, Object parameterObject) {
MappedStatement ms = this.getSqlSession().getConfiguration()
.getMappedStatement(id);
BoundSql boundSql = ms.getBoundSql(parameterObject);
if (boundSql == null) {
throw new RuntimeException("selectId:" + id + " 不存在");
}
return boundSql.getSql();
}
public SqlSession getSqlSession() {
return sqlSession;
}
public static void main(String[] args) {
System.out.println(Integer.MAX_VALUE);
}
}
整个就这么多,这里只是做了一个简单的,对于写到一个文件中或每条记录产生一个文件都需要分页查询再去写,由于时间原因自己没有做优化,这里自己只是记录一下,大牛就别嘲笑了。