2017年12月19日 15:18:57 package com.iflytek.zhejiang.hangzhou.qlsx.serviceimpl; import java.util.List; import org.apache.commons.configuration.Configuration; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.XMLConfiguration; public class XMLParserSample { public static XMLParserSample getConf() { try { return parse(); } catch (ConfigurationException e) { e.printStackTrace(); } return null; } private static XMLParserSample parse() throws ConfigurationException { Configuration config = new XMLConfiguration(XMLParserSample.class.getClassLoader().getResource("conf.xml")); String ip = config.getString("dataBaseURI"); String account = config.getString("account"); String password = config.getString("password"); String runTime = config.getString("runTime"); List<?> tasks = config.getList("tasks.table[@name]"); // List<Table> tblLst = new ArrayList<Table>(); // for (int i = 0; i < tasks.size(); i ) { // // Table tbl = new Table(); // tbl.setName(config.getString(String.format( // "tasks.table(%d)[@name]", i))); // tbl.setInfo(config.getString(String.format( // "tasks.table(%d)[@info]", i))); // tbl.setPrimary(config.getString(String.format( // "tasks.table(%d)[@primary]", i))); // tbl.setColumns(config.getList(String.format( // "tasks.table(%d).columns", i))); // tbl.setTemplate(config.getString(String.format( // "tasks.table(%d)[@template]", i))); // tbl.setWaitTime(config.getString(String.format( // "tasks.table(%d)[@waitTime]", i))); // tbl.setRunTime(config.getString(String.format( // "tasks.table(%d)[@runTime]", i))); // tbl.setSingle(config.getString(String.format( // "tasks.table(%d)[@single]", i))); // tbl.setUrl(config.getString(String.format("tasks.table(%d).url", i))); // // if ( StringUtils.equals(TaskType.MULTI_GETTER, tbl.getTemplate())) { // TableItem item = new TableItem(); // // item.setName(config.getString(String.format( // "tasks.table(%d).item[@name]", i))); // item.setInfo(config.getString(String.format( // "tasks.table(%d).item[@info]", i))); // item.setRef(config.getString(String.format( // "tasks.table(%d).item[@ref]", i))); // item.setColumns(config.getList(String.format( // "tasks.table(%d).item.columns", i))); // item.setUrl(config.getString(String.format("tasks.table(%d).item.url", i))); // // tbl.setItem(item); // } // // tblLst.add(tbl); // } // // gc.setTblLst(tblLst); // // return gc; // return null; } } 有以下几点不理解: demo中的实体bean Table类,demo中没有对应的代码,也没有conf.xml文件,还有最后的那个gc,都不知道是干啥的,导致我很不理解疑问①的遍历getList()到底是什么原理。一脸懵。循环体中无非就是从xml取出对应数据封装到实体bean的属性里面,dao层用的hibernate,但是demo里面没有sql,所以我才猜测是利用的hibernate和数据库表的映射关系来存储数据的,个人也没有学习过hibernate,只是有点接触。最后返回的对象是什么gc是什么也是一头雾水。以上为开发前对demo的整体感受简述。 开发需求说明: <?xml version="1.0" encoding="utf-8"?> <DATAAREA> <CHANGE_FLAG>1</CHANGE_FLAG> <MATERIALS> <MATERIAL> <MATERIALGUID>2fadsfdsfsdc22ed9d</MATERIALGUID> <NAME>水电费水电费水电费</NAME> <FORMAT>1</FORMAT> <DETAIL_REQUIREMENT>一份</DETAIL_REQUIREMENT> <NECESSITY>1</NECESSITY> <NECESSITY_DESC/> <MATERIAL_RES/> <IS_RQ/> <EMPTYTABLE> <FILENAME/> <FILECONTENT/> <FILEURL/> </EMPTYTABLE> <EXAMPLETABLE> <FILENAME/> <FILECONTENT/> <FILEURL/> </EXAMPLETABLE> <BAK/> </MATERIAL> <MATERIAL> <MATERIALGUID>1fsdfdsfsd07a525a</MATERIALGUID> <NAME>发送到发的所发生的</NAME> <FORMAT>1</FORMAT> <DETAIL_REQUIREMENT>1份</DETAIL_REQUIREMENT> <NECESSITY>1</NECESSITY> <NECESSITY_DESC/> <MATERIAL_RES/> <IS_RQ/> <EMPTYTABLE> <FILENAME/> <FILECONTENT/> <FILEURL/> </EMPTYTABLE> <EXAMPLETABLE> <FILENAME/> <FILECONTENT/> <FILEURL/> </EXAMPLETABLE> <BAK/> </MATERIAL> ......等多个<MATERIAL></MATERIAL> </MATERIALS> </DATAAREA>
DROP TABLE IF EXISTS `material_info`; CREATE TABLE `material_info` ( `MATERIALGUID` varchar(255) NOT NULL COMMENT '主键 材料标识', `QLSX_ROWGUID` varchar(50) NOT NULL COMMENT ' AAAA 表中的rowguid对应的字段值', `QLSX_UPDATE_DATE` datetime NOT NULL COMMENT ' AAAA 表中的update_date对应的字段值', `NAME` varchar(512) NOT NULL COMMENT '材料名称', `FORMAT` varchar(8) COMMENT '材料形式,代码项:材料形式', `DETAIL_REQUIREMENT` varchar(100) COMMENT '材料详细要求', `NECESSITY` varchar(8) COMMENT '材料必要性,代码项:材料必要性', `NECESSITY_DESC` varchar(255) COMMENT '材料必要性描述', `IS_RQ` varchar(255) COMMENT '', `BAK` varchar(512) COMMENT '备注', `UPDATE_DATE` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`materialguid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='权力事项库-申报材料主表'; DROP TABLE IF EXISTS `material_res`; CREATE TABLE `material_res` ( `ID` bigint unsigned auto_increment COMMENT '物理主键,无意义', `MATERIALGUID` varchar(255) NOT NULL COMMENT '逻辑主键,参照material_info表中对应的materialguid字段值', `MATERIAL_RES` varchar(255) COMMENT '材料出具单位', `EXAMPLETABLE` CHAR(1) default '0' NOT NULL COMMENT 'FILENAME、FILECONTENT、FILEURL的xml中的父标签是否为EXAMPLETABLE 1是 0不是', `FILENAME` varchar(255) COMMENT '空白表格文件名称(完整文件名,带后缀)', `FILECONTENT` longtext COMMENT '文件内容,BASE64编码格式', `FILEURL` varchar(255) COMMENT '附件链接地址(公有云地址)', `UPDATE_DATE` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='权力事项库-申报材料出具单位和材料信息表'; DROP TABLE IF EXISTS `material_trans_log`; CREATE TABLE `material_trans_log` ( `ID` bigint unsigned auto_increment COMMENT '物理主键,无意义', `QLSX_ROWGUID` varchar(50) NOT NULL COMMENT ' AAAA 表中的rowguid对应的字段值', `QLSX_UPDATE_DATE` datetime NOT NULL COMMENT ' AAAA 表中的update_date对应的字段值', `QLSX_CHANGE_FLAG` varchar(10) NOT NULL COMMENT '0:未变化,1:变化', `CREATE_TIME` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='权力事项库-申报材料解析入库的日志表'; 取出三个字段的值,做参数传给自己写的xml解析方法parse();在解析方法中进行xml解析并进行对应bean的封装。 public XmlParserVO parse(String rowguid,Timestamp updatedate,String materialinfo) throws DocumentException {//参数就是刚刚取出的三个字段的值 Document document = DocumentHelper.parseText(materialinfo); // materialinfo 为xml格式字符串 //一个xml就一个 CHANGE_FLAG 标签,不在material标签内部,故在遍历前取出 String changeFlag = document.selectSingleNode("/DATAAREA/CHANGE_FLAG").getText(); //materialinfo MaterialInfo MaterialTransLog 为新建三张表对应的类bean List<MaterialRes> listRes = new ArrayList<MaterialRes>(); List<MaterialInfo> listInfo = new ArrayList<MaterialInfo>(); MaterialTransLog materialtrauslog = new MaterialTransLog(); materialtrauslog.setQLSX_ROWGUID(rowguid); materialtrauslog.setQLSX_UPDATE_DATE(updatedate); materialtrauslog.setQLSX_CHANGE_FLAG(changeFlag); //获取MATERIALS节点 Node nodeMaterials = document.selectSingleNode("/DATAAREA/MATERIALS"); //取得MATERIALS节点下所有名为“MATERIAL”的子节点,并进行遍历. 遍历后每一个元素就是一组 MATERIAL 标签中的值 List listMaterial = ((Element) nodeMaterials).elements("MATERIAL"); for (Iterator it = listMaterial.iterator(); it.hasNext();) { Element elmMaterial = (Element) it.next(); // 获取一个 MATERIAL 节点 //提前取出materialRes、materialGuid,供下面material_res复用 String materialRes = elmMaterial.element("MATERIAL_RES").getText(); String materialGuid = elmMaterial.element("MATERIALGUID").getText(); MaterialInfo materialInfo = new MaterialInfo(); materialInfo.setMATERIALGUID(materialGuid); materialInfo.setQLSX_ROWGUID(rowguid); materialInfo.setQLSX_UPDATE_DATE(updatedate); materialInfo.setNAME(elmMaterial.element("NAME").getText()); materialInfo.setFORMAT(elmMaterial.element("FORMAT").getText()); materialInfo.setDETAIL_REQUIREMENT(elmMaterial.element("DETAIL_REQUIREMENT").getText()); materialInfo.setNECESSITY(elmMaterial.element("NECESSITY").getText()); materialInfo.setNECESSITY_DESC(elmMaterial.element("NECESSITY_DESC").getText()); materialInfo.setIS_RQ(elmMaterial.element("IS_RQ").getText()); materialInfo.setBAK(elmMaterial.element("BAK").getText()); listInfo.add(materialInfo); /* * EMPTYTABLE EXAMPLETABLE 标签(可能有多个)下 均有FILENAME、FILECONTENT、FILEURL子标签, * 会产生多个数据,遍历后在每一个数据下再进行bean的创建封装,以对应每一条记录。 */ List listEmptytable = elmMaterial.elements("EMPTYTABLE"); for (Iterator it2 = listEmptytable.iterator(); it2.hasNext();) { Element elmEmptytable = (Element) it2.next(); // 获取一个 EMPTYTABLE 节点 MaterialRes materialres = new MaterialRes(); materialres.setMATERIALGUID(materialGuid); materialres.setMATERIAL_RES(materialRes); materialres.setEXAMPLETABLE(EnumNumber.NUMZERO.getNumber()); //枚举类型 值为0 materialres.setFILENAME(elmEmptytable.element("elmEmptytable").getText()); materialres.setFILECONTENT(elmEmptytable.element("FILECONTENT").getText()); materialres.setFILEURL(elmEmptytable.element("FILEURL").getText()); listRes.add(materialres); } List listExampletable = elmMaterial.elements("EXAMPLETABLE"); for (Iterator it3 = listExampletable.iterator(); it3.hasNext();) { Element elmExampletable = (Element) it3.next(); // 获取一个 EXAMPLETABLE 节点 MaterialRes materialres = new MaterialRes(); materialres.setMATERIALGUID(materialGuid); materialres.setMATERIAL_RES(materialRes); materialres.setEXAMPLETABLE(EnumNumber.NUMONE.getNumber()); //枚举类型 值为1 materialres.setFILENAME(elmExampletable.element("elmEmptytable").getText()); materialres.setFILECONTENT(elmExampletable.element("FILECONTENT").getText()); materialres.setFILEURL(elmExampletable.element("FILEURL").getText()); listRes.add(materialres); } } //返回封装好的数据集合 XmlParserVO xmlparservo = new XmlParserVO(listRes, listInfo, materialtrauslog); return xmlparservo; 我把一些细节以及修改在代码中用注释进行了标注,以便于理解。 [java] view plain copy <code class="language-java">@SuppressWarnings("rawtypes") public class GetMaterialInfoDao extends HibernateEntityDao { private SessionFactory sessionFactory; public SessionFactory getSessionFactory() { return sessionFactory; } public void setSessionFactory(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; super.sessionFactory = sessionFactory; } @SuppressWarnings("unchecked") @Transactional public void saveDate(Object obj){ Session session = sessionFactory.getCurrentSession(); session.save(obj); } }</code> 这段代码其实就是我不会用hibernate的体现。-save()方法还用在dao层自己写吗??? ̄□ ̄|| --------------------------------------------------------- 开发过程中考虑的不严谨不周全,【关于这一点,还有,在把解析出的数据存入库之前,再做一个验证,去material_info表里面查询一下这条数据是否已经存在,如果已存在,删了,再把现在刚解析出的数据插入进去,这一点也是我不曾考虑到的】,虽然对业务流程不熟悉,毕竟只是单一接到功能需求,大范围业务流程背景并不清楚,但是严谨周全的工作思路还是必须的。不然就是一堆bug了。。。。 private static final int LIMIT = 50; private final static Executor executor = Executors.newCachedThreadPool();//启用多线程 @Override public void dataHanding() { Long countNum = qltQlsxDao.getCountNum(); int times = 0; if( 0 == countNum % LIMIT ){ times = (int) (countNum / LIMIT); }else{ times = (int) (countNum / LIMIT) 1; } //int times = (int) Math.floor(countNum / LIMIT); //分页查询 避免内存溢出 for (int i = 1; i <= times; i ) { // List<QltQlsxNewDto> dataLst = qltQlsxDao.getMaterialInfo((i - 1) * LIMIT, LIMIT); // if ( null == dataLst || dataLst.isEmpty() ) { // logger.info("无数据需要处理"); // return ; // } final int j=i; executor.execute(new Runnable() { @Override public void run() { try{ List<QltQlsxNewDto> dataLst = qltQlsxDao.getMaterialInfo((j - 1) * LIMIT, LIMIT); if ( null == dataLst || dataLst.isEmpty() ) { logger.info("无数据需要处理"); return ; } parseXMLInfoAndSave(dataLst); }catch(Exception e){ } } }); } }
6、在新建dao层service层时,注意为以后的业务扩展考虑,不同表的增删改查操作方法不要写在一个dao里面,按照业务新建dao。其它层次也是同理。说到这想起了之前在北京的一位同事,当时给我讲解传参的场景,客户需求总是变来变去,有时候参数传递自己不要写的那么死,给自己留条路,便于自己修改,也利于项目代码优化。 |
|