首页 »Java教程 » 图片存入数据库:将XML结点转换成JAVABEAN并存入数据库 »正文
图片存入数据库:将XML结点转换成JAVABEAN并存入数据库
来源: 发布时间:星期四, 2009年1月8日 浏览:6次 评论:0
1.概述 我们要将外部系统给 ![](/icons/83394de.gif) XML文件进行解析 ![](/icons/83394dou.gif) 并存入到数据库 ![](/icons/83394dou2.gif) 但是我们并没有DTD或者Schema ![](/icons/83394dou.gif) 只有 ![](/icons/83394yi.gif) 个WORD格式 ![](/icons/83394de.gif) 介绍说明文档;更离谱 ![](/icons/83394de.gif) 是 ![](/icons/83394dou.gif) XML结点树 ![](/icons/83394de.gif) 结构(即XML结点和XML结点的间 ![](/icons/83394de.gif) 关系)和业务Bean树 ![](/icons/83394de.gif) 结构(即业务Bean和业务Bean ![](/icons/83394de.gif) 关系)并不完全 ![](/icons/83394yi.gif) 致 ![](/icons/83394dou.gif) 比如说 ![](/icons/83394dou.gif) 从业务角度讲 ![](/icons/83394dou.gif) ![](/icons/83394yi.gif) 只猪有只猪头 ![](/icons/83394dou.gif) 而在XML里 ![](/icons/83394dou.gif) 却写成了 pig --content --pighead ![](/icons/83394de.gif) 3级关系 ![](/icons/83394dou.gif) 无端端多了 ![](/icons/83394yi.gif) 个content结点! 没有DTD/Schema ![](/icons/83394dou.gif) 结构又不规范标准 ![](/icons/83394dou.gif) 我们就没法用自动化 ![](/icons/83394de.gif) 第 3方JAVA转换API进行解析 ![](/icons/83394dou.gif) 而只能手动地、 ![](/icons/83394yi.gif) 个 ![](/icons/83394yi.gif) 个地解析 ![](/icons/83394dou2.gif) 但在手动解析 ![](/icons/83394de.gif) 过程中 ![](/icons/83394dou.gif) 我们仍然发现各个结点 ![](/icons/83394de.gif) 解析和入库中有很多东西是共同 ![](/icons/83394de.gif) ![](/icons/83394dou.gif) 或者有共同 ![](/icons/83394de.gif) 规律 ![](/icons/83394dou.gif) 这些东西可以抽出来作为 ![](/icons/83394yi.gif) 个准框架 ![](/icons/83394dou.gif) 然后再将结点中区别 ![](/icons/83394de.gif) 部分开放出来 ![](/icons/83394dou.gif) 允许具体 ![](/icons/83394de.gif) 结点做具体 ![](/icons/83394de.gif) 实现 ![](/icons/83394dou.gif) 并最终形成 ![](/icons/83394yi.gif) 个半自动 ![](/icons/83394de.gif) 解析/入库框架 ![](/icons/83394dou2.gif) 为什么说它是半自动 ![](/icons/83394de.gif) ?它有哪些限制? 自动:不必为每个结点编写XML 解析代码和入库代码 “半”:需手动地编写每个JAVABEAN ![](/icons/83394dou.gif) 并手动地为每个BEAN建表 限制: a.所有业务字段 ![](/icons/83394de.gif) 类型只能设为STRING/VARCHAR ![](/icons/83394dou.gif) 并且非业务字段 ![](/icons/83394de.gif) 类型在BEAN中不能为STRING b.BEAN名和表名必须相同 ![](/icons/83394dou.gif) 或者可以进行 ![](/icons/83394yi.gif) 对 ![](/icons/83394yi.gif) 映射 c.BEAN ![](/icons/83394de.gif) 成员变量名必须和XML结点 ![](/icons/83394de.gif) 属性名/元素名相同 ![](/icons/83394dou.gif) 或者可以进行 ![](/icons/83394yi.gif) 对 ![](/icons/83394yi.gif) 映射 这 3种限制都是利用JAVA反射机制进行自动操作 ![](/icons/83394de.gif) 前提 ![](/icons/83394dou2.gif) 2.基本思想 所谓 ![](/icons/83394de.gif) XML解析 ![](/icons/83394dou.gif) 就是将XML结点转换成JAVABEAN例子 ![](/icons/83394dou.gif) XML结点 ![](/icons/83394de.gif) ATTRIBUTE值和ELEMENT值就是JAVABEAN例子 ![](/icons/83394de.gif) 成员变量值; 所谓 ![](/icons/83394de.gif) 持久化 ![](/icons/83394dou.gif) 就是将JAVABEAN例子变成数据库对应表中 ![](/icons/83394de.gif) ![](/icons/83394yi.gif) 条记录 ![](/icons/83394dou.gif) JAVABEAN例子 ![](/icons/83394de.gif) 成员变量值就是记录中某个字段 ![](/icons/83394de.gif) 值 ![](/icons/83394dou.gif) 或者其他表中某个参考了该记录 ![](/icons/83394de.gif) 另 ![](/icons/83394yi.gif) 条记录 ![](/icons/83394dou2.gif)
而在XML中 ![](/icons/83394dou.gif) JAVABEAN体系中 ![](/icons/83394dou.gif) 数据据表关系结构中 ![](/icons/83394dou.gif) 结点和结点的间 ![](/icons/83394de.gif) 关系都是树形 ![](/icons/83394de.gif) 关系 ![](/icons/83394dou2.gif) 整体 ![](/icons/83394de.gif) 解析和入库 ![](/icons/83394dou.gif) 就是在遍历树时执行转换动作 ![](/icons/83394dou2.gif) 而我们知道 ![](/icons/83394dou.gif) 树 ![](/icons/83394de.gif) 遍历是可以用递归算法实现 ![](/icons/83394de.gif) ![](/icons/83394dou.gif) 而递归 ![](/icons/83394dou.gif) 就不用说了吧 ![](/icons/83394dou.gif) 它是实现 ![](/icons/83394chengxu.gif) “自动化” ![](/icons/83394de.gif) 主要途径的 ![](/icons/83394yi.gif) ![](/icons/83394dou2.gif) 以下是对各“树” ![](/icons/83394de.gif) 具体分析: 假设两个业务实体A和B的间存在聚合关系(父子关系) ![](/icons/83394dou2.gif) 那么具体可分 3种情况: a.B是 ![](/icons/83394yi.gif) 个原子字段(即不可再分) ![](/icons/83394dou.gif) 并且是A ![](/icons/83394de.gif) ![](/icons/83394yi.gif) 个属性 ![](/icons/83394dou2.gif) XML中 ![](/icons/83394dou.gif) B是A ![](/icons/83394de.gif) XML ATTRIBUTE或者A ![](/icons/83394de.gif) 原子ELEMENT BEAN中 ![](/icons/83394dou.gif) B是A ![](/icons/83394de.gif) 成员变量 ![](/icons/83394dou.gif) 并且B是 ![](/icons/83394yi.gif) 个JAVA内置 ![](/icons/83394de.gif) 数据类型 数据库中 ![](/icons/83394dou.gif) B是A表 ![](/icons/83394de.gif) ![](/icons/83394yi.gif) 个列 b.B是 ![](/icons/83394yi.gif) 个复合字段 ![](/icons/83394dou.gif) 并且是A ![](/icons/83394de.gif) ![](/icons/83394yi.gif) 个属性 ![](/icons/83394dou.gif) 而且和A是1:1关系 XML中 ![](/icons/83394dou.gif) B是A ![](/icons/83394de.gif) ELEMENT ![](/icons/83394dou.gif) 并且B有自己 ![](/icons/83394de.gif) ELEMENT或者ATTRIBUTE BEAN中 ![](/icons/83394dou.gif) B是A ![](/icons/83394de.gif) 成员变量 ![](/icons/83394dou.gif) 并且 ![](/icons/83394chengxu.gif) 中有个B类 数据库中 ![](/icons/83394dou.gif) B表是A表 ![](/icons/83394de.gif) 子表(即B外键参考了A表) c.B是 ![](/icons/83394yi.gif) 个复合字段 ![](/icons/83394dou.gif) 并且是A ![](/icons/83394de.gif) ![](/icons/83394yi.gif) 个属性 ![](/icons/83394dou.gif) 而且和A是N:1关系 XML中 ![](/icons/83394dou.gif) B是A ![](/icons/83394de.gif) ELEMENT ![](/icons/83394dou.gif) 并且B有自己 ![](/icons/83394de.gif) ELEMENT或者ATTRIBUTE BEAN中 ![](/icons/83394dou.gif) B组成 ![](/icons/83394yi.gif) 个类集(List,Set)共同作为A ![](/icons/83394de.gif) 成员变量 ![](/icons/83394dou.gif) 并且 ![](/icons/83394chengxu.gif) 中有个B类 数据库中 ![](/icons/83394dou.gif) B表是A表 ![](/icons/83394de.gif) 子表(即B外键参考了A表) 了解了这 3种情况 ![](/icons/83394dou.gif) 接下来就好办了 ![](/icons/83394dou2.gif) ![](/icons/83394chengxu.gif) 每抓到 ![](/icons/83394yi.gif) 个结点 ![](/icons/83394dou.gif) 都要递归地进行以下处理:先处理它 ![](/icons/83394de.gif) 原子属性(情形a) ![](/icons/83394dou.gif) 接着处理它 ![](/icons/83394de.gif) 单个子结点(情形b) ![](/icons/83394dou.gif) 最后处理它 ![](/icons/83394de.gif) 类集子结点( 情形c) ![](/icons/83394dou2.gif) 3.代码实现 ![](/icons/83394de.gif) 重点 两个重点: a.如何让业务实体在 3棵树内 ![](/icons/83394yi.gif) ![](/icons/83394yi.gif) 对应好? b.如何发现树形关系 ![](/icons/83394dou.gif) 比如A ![](/icons/83394de.gif) 属性有哪些 ![](/icons/83394dou.gif) A ![](/icons/83394de.gif) 子结点有哪些? 问题a很简单 ![](/icons/83394dou.gif) 就是让 3棵树里相同 ![](/icons/83394de.gif) 业务实体取相同 ![](/icons/83394de.gif) 名字 ![](/icons/83394dou2.gif)
a.解析XML时发现 结点X ![](/icons/83394de.gif) 属性Y 等于 值Z ![](/icons/83394dou.gif) 则执行PropertyUtils. ![](/icons/83394set.gif) Property(结点X , 属性Y , 值Z)即可 ![](/icons/83394dou2.gif) 在这里X ![](/icons/83394dou.gif) Y,Z是变量 ![](/icons/83394dou.gif) ![](/icons/83394chengxu.gif) 不用关心具体 ![](/icons/83394de.gif) 结点和属性是哪些个 ![](/icons/83394dou2.gif) 需要注意 ![](/icons/83394de.gif) 是 ![](/icons/83394dou.gif) 如果属性Y是原子字段 ![](/icons/83394dou.gif) 则要求属性Y必须为String类型 ![](/icons/83394dou.gif) 否则 ![](/icons/83394chengxu.gif) 不知道将值Z转换成哪种类型(注:有关PropertyUtils ![](/icons/83394dou.gif) 请见apache commons Beanutils ) b.入库时发现x.getY ![](/icons/83394kh.gif) =z ![](/icons/83394dou2.gif) 如果属性y是原子字段 ![](/icons/83394dou.gif) 则执行SQL insert ![](/icons/83394int.gif) o X(...,y,...) values (...,z,...) ![](/icons/83394dou.gif) 这里要求y字段必须为varchar/char类型 ![](/icons/83394dou.gif) 以免发生类型转换 ![](/icons/83394cuowu.gif) . 有关问题b XML树:JDOM, dom4j等都可以直接找到父子关系 BEAN体系: I.原子属性 ![](/icons/83394dou2.gif) 我们限定 ![](/icons/83394yi.gif) 个BEAN中所有有业务意义 ![](/icons/83394de.gif) 原子字段 ![](/icons/83394de.gif) 类型都STRING ![](/icons/83394dou.gif) 所有String类型 ![](/icons/83394de.gif) 字段都是业务字段 II.单个子结点 ![](/icons/83394dou2.gif) 我们让所有有业务意义 ![](/icons/83394de.gif) 非原子字段都实现 ![](/icons/83394yi.gif) 个共同 ![](/icons/83394de.gif) 接口BusiNode ![](/icons/83394dou.gif) 这样 ![](/icons/83394yi.gif) 个BEAN中所有BusiNode成员都是这个BEAN ![](/icons/83394de.gif) 子结点 III.类集子结点 ![](/icons/83394dou2.gif) 我们也可以限定所有且只有类集子结点可以使用List或Set类型 ![](/icons/83394dou.gif) 这样可以利用过滤出所有类集子结点 ![](/icons/83394dou2.gif) 然而 ![](/icons/83394dou.gif) 在JAVA1.4及以前 ![](/icons/83394de.gif) 版本里 ![](/icons/83394dou.gif) ![](/icons/83394chengxu.gif) 并不知道过滤出 ![](/icons/83394de.gif) 类集子结点是哪个Class ![](/icons/83394de.gif) 例子( ![](/icons/83394yinwei.gif) 没有泛型) ![](/icons/83394dou.gif) 也就没办法例子化 ![](/icons/83394yi.gif) 个类集子结点(见后文) ![](/icons/83394dou.gif) 因此只能手动注册类集子结点 ![](/icons/83394de.gif) 属性名和Class ![](/icons/83394dou2.gif) JAVA1.5以上 ![](/icons/83394de.gif) 版本我没用过 ![](/icons/83394dou.gif) 不知道可不可以解决这个问题 ![](/icons/83394dou2.gif) 数据库表关系: 这就不用多说了 ![](/icons/83394dou.gif) 就是通过外键参考 ![](/icons/83394dou2.gif) 因此每类结点对应 ![](/icons/83394de.gif) 表中 ![](/icons/83394dou.gif) 都必须有个外键 ![](/icons/83394dou.gif) 以参考它 ![](/icons/83394de.gif) 父结点;还必须有个主键 ![](/icons/83394dou.gif) 以供它 ![](/icons/83394de.gif) 子结点参考 ![](/icons/83394dou2.gif) 各表 ![](/icons/83394de.gif) 外键名必须相同并为 ![](/icons/83394yi.gif) 常数 ![](/icons/83394dou.gif) 否则 ![](/icons/83394chengxu.gif) 生成INSERT SQL时才可以不用理会具体表 ![](/icons/83394de.gif) 具体 ![](/icons/83394de.gif) 外键名
![](/icons/83394chengxu.gif) 在解析时 ![](/icons/83394dou.gif) 遍历 ![](/icons/83394de.gif) 是BEAN树;在持久化时也是 ![](/icons/83394dou2.gif) 比起XML树 ![](/icons/83394dou.gif) BEAN树代表真正 ![](/icons/83394de.gif) 业务结构;比起数据库表关系树 ![](/icons/83394dou.gif) BEAN树才能由父至子地进行先序遍历 4.其他问题 a.要让 ![](/icons/83394chengxu.gif) 知道 ![](/icons/83394dou.gif) 原子属性中哪些是XML结点 ![](/icons/83394de.gif) 属性 ![](/icons/83394dou.gif) 哪些是XML结点 ![](/icons/83394de.gif) 原子ELEMENT ![](/icons/83394dou2.gif) 代码中这是两个抽象思路方法 ![](/icons/83394dou.gif) 必须让具体 ![](/icons/83394de.gif) 结点类实现 b.回顾本文概述部分提到 ![](/icons/83394de.gif) “pig --content --pighead ![](/icons/83394de.gif) 3级关系 ![](/icons/83394dou.gif) 无端端多了 ![](/icons/83394yi.gif) 个content结点” ![](/icons/83394dou.gif) 因此我们要让 ![](/icons/83394chengxu.gif) 知道 ![](/icons/83394dou.gif) pighead,pigfoot等结点 ![](/icons/83394de.gif) 子结点 ![](/icons/83394dou.gif) 究竟是pig ![](/icons/83394dou.gif) 还是pig下 ![](/icons/83394de.gif) content ![](/icons/83394dou2.gif) 处理不规范标准XML时要注意这个问题 ![](/icons/83394dou2.gif) 这也是 ![](/icons/83394yi.gif) 个抽象思路方法 ![](/icons/83394dou.gif) 必须让具体 ![](/icons/83394de.gif) 结点类实现 c.和上 ![](/icons/83394yi.gif) 条类似但更变态 ![](/icons/83394de.gif) ![](/icons/83394dou.gif) 是类集结点 ![](/icons/83394de.gif) 不规范标准问题 ![](/icons/83394dou2.gif) 假设 ![](/icons/83394yi.gif) 个pig有多个pighead ![](/icons/83394dou.gif) 那结构可能为 pig--pighead,pighead,... ![](/icons/83394dou.gif) 也可能为pig--pigheads--content,content.... 必须让 ![](/icons/83394chengxu.gif) 知道某个具体结点用 ![](/icons/83394de.gif) 是哪种模式 5.代码 核心:多态 + 递归 a.接口BusiNode import java.util.*; import org.dom4j.Element; /** * 每个结点都要实现 接口 * 它提供了 些思路方法以方便实现递归 XML解析和持久化 * */ public erface BusiNode { /** * 所有类型为不可分类型 属性 * @ 属性名 集合 */ public List getAtomicPropNames ; /** * 些成员变量 这些成员变量是XML结点 属性 * @![](/icons/83394return.gif) */ public List getXmlAttributes ; /** * 些成员变量 这些成员变量是XML结点 子元素 并且类型为不可分![](/icons/83394de.gif) * @![](/icons/83394return.gif) */ public List getXmlAtomicElements ; /** * 所有类型为类集 属性 并且这些类集中每个元素 类型都是BusiNode * @ key = 属性名, value = 属性类 Class对象![](/icons/83394dou2.gif) * 如果为空不返回NULL 而是空 MAP */ public Map getCollectionPropsMap ; /** * 所有类型为BusiNode 属性 * @ 属性名 集合 */ public List getBusiNodePropNames ; /** * 从XML中解析出来![](/icons/83394dou2.gif) * @param element * @![](/icons/83394return.gif) */ public void parseFromXML(Element element); }
b.默认 ![](/icons/83394de.gif) 实现 import java.lang.reflect.Field; import java.util.*; import org.apache.commons.beanutils.PropertyUtils; import org.dom4j.Attribute; import org.dom4j.Element; /** * 默认 BUSI NODE 继承此类 BUSI NODE 需满足 所有不可分属性集=String类型 属性集 * MyUtils类 代码欠奉 * */ public abstract DefaultBusiNode implements BusiNode { public List getAtomicPropNames { MyUtils.getFieldNamesOfClass(this.getClass , String. ); } public List getBusiNodePropNames { MyUtils.getFieldNamesOfClass(this.getClass , BusiNode. ); } /* * 所有子元素 父元素 有时是本结点 有时是本结点下 元素 变态 */ public abstract Element getXmlElementParent(Element rootElement); /* * 类集子结点根元素 Iterator 假设 个pig有多个pighead![](/icons/83394dou.gif) * 那结构可能为 pig--pighead,pighead,...![](/icons/83394dou.gif) * 也可能为pig--pigheads--content,content.... * 必须让 知道某个具体结点用 是哪种模式 * * 如果为空则返回 个空类集 Iterator 不要返回NULL */ public abstract Iterator getCollectionElementIterator( Element xmlElementParent, String attName); /** * 解析XML属性 * * @param rootElement */ protected void parseAttributesFromXml(Element rootElement) { List xmlAttributes = this.getXmlAttributes ; for ( i = 0; i < this.getXmlAttributes .size ; i ) { String attName = (String) xmlAttributes.get(i); Attribute att = rootElement.attribute(attName); (att != null) { try { PropertyUtils. Property(this, attName, att.getValue ); } catch (Exception e) { throw RuntimeException(e); } } } } /** * 解析不可分 Element * * @param rootElement */ protected void parseAtomicElementFromXml(Element rootElement) { Element xmlElementParent = getXmlElementParent(rootElement); (xmlElementParent null) { ; } List xmlElements = this.getXmlAtomicElements ; for ( i = 0; i < xmlElements.size ; i ) { String attName = (String) xmlElements.get(i); Element elmt = xmlElementParent.element(attName); (elmt != null) { try { PropertyUtils. Property(this, attName, elmt.getText ); } catch (Exception e) { throw RuntimeException(e); } } } } /** * 解析BusiNode属性 * * @param rootElement */ protected void parseBusiNodeElementFromXml(Element rootElement) { Element xmlElementParent = getXmlElementParent(rootElement); (xmlElementParent null) { ; } // 再解析BusiNode属性 List busiNodePropNames = this.getBusiNodePropNames ; for ( i = 0; i < busiNodePropNames.size ; i ) { try { String attName = (String) busiNodePropNames.get(i); Element elmt = xmlElementParent.element(attName); (elmt != null) { Field field = this.getClass .getDeclaredField(attName); BusiNode att = (BusiNode) field.getType . Instance ; att.parseFromXML(elmt); PropertyUtils. Property(this, attName, att); } } catch (Exception e) { throw RuntimeException(e); } } } /** * 解析类集属性 * * @param rootElement */ protected void parseCollectionPropsFromXml(Element rootElement) { // 先解析XML属性 Element xmlElementParent = getXmlElementParent(rootElement); (xmlElementParent null) { ; } // 最后解析类集属性 Map collectionPropsMap = this.getCollectionPropsMap ; for (Iterator it = collectionPropsMap.keySet .iterator ; it.hasNext ;) { try { String attName = (String) it.next ; Collection coll = (Collection) PropertyUtils.getProperty(this, attName); Class attType = (Class) collectionPropsMap.get(attName); Iterator collElementsIt = this.getCollectionElementIterator( xmlElementParent, attName); // xmlElementParent.elementIterator(attName); while (collElementsIt.hasNext ) { Element collElmt = (Element) collElementsIt.next ; BusiNode sinlgeAtt = (BusiNode) attType. Instance ; sinlgeAtt.parseFromXML(collElmt); coll.add(sinlgeAtt); } } catch (Exception e) { throw RuntimeException(e); } } } /** * 从XML中解析出结点 此思路方法可能抛出RumtimeException */ public void parseFromXML(Element rootElement) { this.parseAttributesFromXml(rootElement); this.parseAtomicElementFromXml(rootElement); this.parseBusiNodeElementFromXml(rootElement); this.parseCollectionPropsFromXml(rootElement); } } /** * 入库 * JdbcUtil,MyUtils 代码欠奉 * */ public BusiNodeDAO { private Long saveBusiNode(BusiNode node, Long parentNodeId) { // 先存储原子属性 Long id = saveBareBusiNode(node, parentNodeId); // 再存储类集属性 Map collectionPropsMap = node.getCollectionPropsMap ; for (Iterator it = collectionPropsMap.keySet .iterator ; it.hasNext ;) { String attName = (String) it.next ; Collection coll = null; try { coll = (Collection) PropertyUtils.getProperty(node, attName); } catch (Exception e) { throw RuntimeException("编码 "); } for (Iterator iitt = coll.iterator ; iitt.hasNext ;) { BusiNode subNode = (BusiNode) iitt.next ; saveBusiNode(subNode, id); } } // 最后存储所有BusiNode属性 Iterator iitt = node.getBusiNodePropNames .iterator ; while (iitt.hasNext ) { BusiNode subNode = null; try { subNode = (BusiNode) PropertyUtils.getProperty(node, (String) iitt.next ); } catch (Exception e) { throw RuntimeException("编码 "); } (subNode != null) { saveBusiNode(subNode, id); } } id; } /** * 插入某个BusiNode 根结点 此思路方法可能抛出RuntimeException * * @param node * @![](/icons/83394return.gif) */ private Long saveBareBusiNode(BusiNode node, Long parentNodeId) { StringBuffer sbForSql = StringBuffer ; List paramValues = ArrayList ; genInsertSqlAndParam(node, parentNodeId, node.getAtomicPropNames , sbForSql, paramValues); Long(JdbcUtil.queryForLong( sbForSql.toString , paramValues.toArray )); } /** * 生成某个结点 插入语句和paramValues![](/icons/83394shuzu.gif) 此思路方法可能抛出RuntimeException * * @param node * @param columnNames * @param sbForSql * @param paramValues */ private void genInsertSqlAndParam(BusiNode node, Long parentNodeId, List columnNames, StringBuffer sbForSql, List paramValues) { sbForSql.append(" insert o "); sbForSql.append(MyUtils.getClassBareName(node.getClass )); List cns = ArrayList ; cns.addAll(columnNames); cns.add("parentNodeId"); sbForSql.append(MyUtils.encloseWithCurve(MyUtils .joinCollectionStrings(cns, ","))); sbForSql.append(" values "); List qms = ArrayList ; // 问号 for (Iterator it = columnNames.iterator ; it.hasNext ;) { qms.add("?"); String cn = (String) it.next ; try { paramValues.add(PropertyUtils.getProperty(node, cn)); } catch (Exception e) { throw RuntimeException(e); } } qms.add("?"); // parentNodeId paramValues.add(parentNodeId); sbForSql.append(MyUtils.encloseWithCurve(MyUtil .joinCollectionStrings(qms, ","))); sbForSql.append(";select @@identity"); } }
相关文章
读者评论
发表评论
|
|