java批量插入数据库之写绑定变量

2023-10-29

最近查到关于sql批量写入和绑定变量的问题,看到了很多好的帖子,再次进行总结


数据库在执行SQL语句时会首先解析SQL语句,解析又分为硬解析与软解析。说到硬解析和软解析,就不能不说一下Oracle对sql的处理过程。当你发出一条sql语句交付Oracle,在执行和获取结果前,Oracle对此sql将进行几个步骤的处理过程:

1、语法检查(syntax check)

  检查此sql的拼写是否语法。

2、语义检查(semantic check)

   诸如检查sql语句中的访问对象是否存在及该用户是否具备相应的权限。

3、对sql语句进行解析(prase)

   利用内部算法对sql进行解析,生成解析树及执行计划。

4、执行sql,返回结果(execute and return)。

其中,软、硬解析就发生在第三个过程里,Oracle利用内部的hash算法来取得该sql的hash值,然后在librarycache里查找是否存在该hash值。假设存在,则将此sql与cache中的进行比较(注意此处的比较哪怕是一个字母的大小写、空格个数不一致都会认为不同)。假设“相同”,就将利用已有的解析树与执行计划,而省略了优化器的相关工作。这也就是软解析的过程;如果上面的2个假设中任有一个不成立,那么优化器都将进行创建解析树、生成执行计划的动作。这个过程就叫硬解析。由此可以看出应该极力避免硬解析,尽量使用软解析。

通过http://blog.csdn.net/duanning397/article/details/7586609 我们看出两者的差距还是很大的


那么如何进行软解析,在这里主要通过绑定变量的方法


      认识绑定变量:

  绑定变量是为了减少解析,比如你有个语句这样的:

  select aaa,bbb from ccc where ddd=eee;

  如果经常通过改变eee这个谓词赋值来查询,如下:

  select aaa,bbb from ccc where ddd=fff;
  select aaa,bbb from ccc where ddd=ggg;
  select aaa,bbb from ccc where ddd=hhh;

  每条语句都要被数据库解析一次,这样比较浪费资源,如果把eee换成绑定变量形式,无论ddd后面是什么值,都不需要重复解析

通过


那么如何在java中实现绑定变量,主要用两种方法,一种是?号法,比较简单粗暴,适合大部分情况

具体可以参考http://blog.csdn.net/wacthamu/article/details/7798393 这里转载一些关键内容

 Java实现绑定变量的方法:

PreparedStatement pstmt = con.prepareStatement("UPDATE employees SET salay = ? WHERE id = ?");
pstmt.setBigDecimal(1, 15.00);
pstmt.setInt(2, 110592);
//result statmement:   UPDATE employees SET salay = 15.00 WHERE id =110592
pstmt.executeQuery();

  假设要将id从1到10000的员工的工资都更新为150.00元,不使用绑定变量,则:

sql.executeQuery("UPDATE employees SET salay = 150.00 WHERE id = 1");
sql.executeQuery("UPDATE employees SET salay = 150.00 WHERE id = 2");
sql.executeQuery("UPDATE employees SET salay = 150.00 WHERE id = 3");
sql.executeQuery("UPDATE employees SET salay = 150.00 WHERE id = 4");
....
sql.executeQuery("UPDATE employees SET salay = 150.00 WHERE id = 10000");

  使用绑定变量,则:

PreparedStatement pstmt;
for (id = 1; id < 10000; id++)
{
   if (null == pstmt)
     pstmt = con.prepareStatement("UPDATE employees SET salay = ? WHERE id = ?");
   pstmt.setBigDecimal(1, 150.00);
   pstmt.setInt(2, id);
   pstmt.executeQuery();
}
       需要注意的是pstmt.executeQuery();是每次都打开游标,所以出国处理大数据的话,则需要在后面添加pstmt.close();

  这里可以看到通过设置的方式可以让数据库认为成一条语句,这里必须按照这种方法,如果用简单的字符串拼接的方法,数据库依然认为成两条语句具体可以参考http://www.itpub.net/thread-263389-1-1.html


那么第二种方法是什么呢,细心的网友可以看到http://blog.csdn.net/wacthamu/article/details/7798393 已经提及,即使用:x的方式,其中该文章,也给出了一样的赋值方式,

其实Oracle遵循针对PL/SQL存储过程使用占位符名称匹配的原则,而针对SQL语句则采用占位符位置匹配的原则。所以上文的:x更多的是在Oracle中的本身里面,对比两者可以发现,一种是单纯的问号,一种是用变量名,当赋值的变量是重复的时候,用后者可以避免重复书写,但后者由于是变量名,也会导致书写错误,

在近期研究中发现,在hibernate中的hql语言其实也是可以占位符名称匹配,这里给出一个完整的hql的存储例子

<span style="color:#333333;">StringBuffer hql = new StringBuffer();
        hql.append("select distinct employee  from PreceptPO pre,PlanPO plan, ").append(
                "EmployeeInfoPO employee,ObjectRelationPO relation ");
        hql.append(" where pre.oid=plan.preceptID");
        hql.append(" and pre.status='").append(PreceptStatusType.STARTUP.getCode()).append("'");
        hql.append(" and plan.objectID=employee.oid ");
        hql.append(" and relation.relationObjectID=:employeeID ");
        hql.append(" and relation.preceptID=plan.preceptID ");
        hql.append(" and relation.objectID=plan.objectID ");
        hql.append(" and relation.phase=plan.phase ");
        hql.append(" and (relation.performanceRole=3 or relation.performanceRole=4 )");
        

        //员工状态
        hql.append(" and ");
        DAOHelper.buildOrHql(hql, "employee.employeeStatus",
                StaffStatusAttribute.Normal_Employee.getStatus());

        Query q = getSession().createQuery(hql.toString());
        /*if(empList.size() > 0){
        	</span><span style="color:#ff0000;"><strong>q.setParameterList("empList", empList);	</strong></span><span style="color:#333333;">
        }*/
        
        q.setLong("employeeID", appraiserID);</strong>
        objectList = q.list();
        
        List voList = new ArrayList(objectList.size());
        for (Iterator iter = objectList.iterator(); iter.hasNext();) {
            EmployeeInfoPO emp = (EmployeeInfoPO) iter.next();
            voList.add(EmployeeBasicConvert.convert(emp));
        }
    	return voList;
	}</span>

这个时候很多人会说,既然使用了createQuery,那使用createSQLQuery可不可以用占位符名称匹配,答案是可以的,下面给出了例子

StringBuffer buffer = new StringBuffer();
/*
		buffer.append(" select count(1) as num from TB_PMG_OBJECTRELATION orn,TB_PMG_PLAN pl ")
		      .append(" left join TB_PMG_EVALUATESCORE on TB_PMG_EVALUATESCORE.c_planid = pl.c_oid_plan ")
	          .append(" and TB_PMG_EVALUATESCORE.c_status in (2,3,5,7) ")
	          .append(" where pl.c_oid_plan=").append(planID)
	          .append(" and pl.c_objectid = orn.c_objectid ")
	          .append(" and orn.c_preceptid = pl.c_preceptid and orn.c_phase = pl.c_phase ")
	          .append(" and orn.c_level = '2' and orn.c_businessrole='1' ")
	          .append("  and TB_PMG_EVALUATESCORE.C_OID_EVALUATESCORE is not null");
*/
		buffer.append(" SELECT COUNT(1) AS NUM FROM TB_PMG_OBJECTRELATION ORN  ")
	      .append(" LEFT JOIN  TB_PMG_EVALUATESCORE e on e.C_STATUS IN (2,3,5,7)")
	      .append(" AND ORN.C_PRECEPTID = e.c_preceptID ")
	      .append(" AND ORN.C_PHASE = e.c_phase ")
	      .append(" AND ORN.C_objectID = e.c_objectID ")
	      .append(" WHERE  ")
	      .append(" ORN.C_OBJECTID =:objectID  ")
	      .append(" AND ORN.C_PRECEPTID = :preceptID AND ORN.C_PHASE = :phase ")
	      .append(" AND ORN.C_LEVEL = '2' AND ORN.C_BUSINESSROLE='1' ")
	      .append(" AND e.C_OID_EVALUATESCORE IS NOT NULL ");

		SQLQuery q= loadSession().createSQLQuery(buffer.toString());
		q.setParameter("preceptID", preceptID);
		q.setParameter("phase", phase);
		q.setParameter("objectID", objectID);</strong>
		q.addScalar("num", Hibernate.LONG);
		List list = q.list();



其实在大型工程中,占位符名称匹配用的很多,但如果就是用单纯的sql语句怎么实现呢?,下文给出了方式http://blog.csdn.net/keyboardsun/article/details/4275594

这里需要用一个自定义函数,进行拼接赋值,这里面还对不用类型的内容进行转换,比如时间,数字等比较复杂的转换,所以这个自定义函数可以作为一个工具类


很感谢以上所有的博主,给我的帮助,在这里也专程感谢


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java批量插入数据库之写绑定变量 的相关文章

随机推荐

  • Java学习笔记(十九)

    Spring Cloud 什么是Spring Cloud Spring cloud 应用程序启动器是基于 Spring Boot 的 Spring 集成应用程序 提供与外部系统的集成 更专注于服务治理 Spring cloud Task 一
  • eix安装_U盘安装原版Windows7

    教程简介 本教程为U盘安装原版Windows 7 我将带领大家学习如何用U盘安装原版的Windows7系统 希望对大家有帮助 在开始安装之前需要了解常见电脑的U盘启动按键都有哪些 请仔细阅读下表 安装步骤 一定要看步骤3 不然造成数据损坏概
  • 爬虫入门第2课:代理池的设计

    爬虫学习知识点及案例篇 汇总 爬虫入门第1课 代理池概述及开发环境 本阶段带大家从代理池的设计开始 学习Python爬虫及项目实战 详情关注上方专栏 1 代理池的工作流程 目标 理解代理池的工作流程 以及 各个模块的作用 内容介绍 代理池的
  • Java-API简析_java.net.InetAddress类(基于 Latest JDK)(浅析源码)

    版权声明 未经博主同意 谢绝转载 请尊重原创 博主保留追究权 https blog csdn net m0 69908381 article details 131590559 出自 进步 于辰的博客 因为我发现目前 我对Java API的
  • 模板引擎 template

    1 特性 性能卓越 执行速度通常是Mustache与tmpl的20多倍 性能测试 支持运行时调试 可精确定位异常模板所在的语句 对NodeJS Express友好支持 安全 默认对输出进行转义 在沙箱中运行编译后的代码 Node版本可以安全
  • SQL Server批处理运行时错误的影响

    前言 批处理是同时从应用程序发送到 SQL Server 2005 并得以执行的一组单条或多条 Transact SQL 语句 我们通常认为当一个批处理的多条语句中有一条发生运行时错误 将停止执行批处理中当前语句和它之后的语句 这使得在实际
  • Seq2Seq实战——机器翻译

    基于seq2seq做一个机器翻译 我们将使用PyTorch和TorchText构建一个机器学习模型 从一个序列到另一个序列 将德语到英语翻译成英语 该模型是 Sequence to Sequence Learning with Neural
  • 简单html文件上传带参数

    html的代码如下
  • 2021SC@SDUSC Zxing开源代码(十六)PDF417二维码(二)

    2021SC SDUSC 目录 一 BarcodeMatrix 二 BarcodeRow 三 Compaction 四 Dimensions 五 PDF417ErrorCorrection 六 PDF417HighLevelEncoder
  • [创业之路-57] :商业计划书BP如何书写?总体框架!

    引言 BP Buiness Plan 即商业计划书 本质上还是一份计划 是一份商业计划 即一种关于如何赚钱的计划 是一份通过组建公司 运营项目 进而赚钱的项目计划 什么是商业 商业 是一种有组织的提供顾客所需的物品与服务 都可以称为产品 的
  • 逻辑运算符&&、&、

    运算符 和 以及 和 的区别 逻辑运算符 与 只要有一边为fale 那么就是false 或 只要有一边为true 那么就是true 异或 只要是相同的boolean值 那么就是false 不相同才是true 逻辑运算符 双与 双或 解释 双
  • Qt小项目1 计算器

    头文件 ifndef WIDGET H define WIDGET H include
  • 资产设备管理系统方案,什么是智能设备管理系统?

    文章目录 一 设备信息管理 二 设备使用管理 三 设备租赁管理 四 设备运行管理 五 设备维修维保管理 六 资产设备管理应用价值 茗鹤设备管理信息系统以资产设备和备件为基本管理对象 覆盖资产生命周期 调试 运行 计划 维护 修复 分析和报废
  • 安陌陌咩咩咩

    include
  • virtualBox虚拟机没有64位选项

    问题解决 首先 你要确认你的CPU是64位的 如果是那么继续查看 然后 进入BIOS将 intel virtual technology 设置为 enable 如何进入BIOS 自行百度 根据自己电脑型号搜索一般是开机按F2 联想z470
  • react学习笔记-从井字棋开始(2)

    前言 接着前面的空格子棋 加上其他功能变成真正的井字棋 数字显示添加 传值 prop 方式 修改 Board 类的renderSquare函数 class Board extends React Component renderSquare
  • 一个数组实现两个栈(共享栈)

    题目 一个数组实现两个栈 方法1 下标为0的位置为栈1的栈底 下标为1的位置为栈2的栈底 栈1的元素存放在下标为偶数的位置上 栈2的元素放在下标为奇数的位置上 如上图所示的数组 若栈1有一个元素 2 栈2有6个元素 1 2 3 4 5 6
  • UnityShader _Object2World与UNITY_MATRIX_MVP被替换

    1 Object2World 模型空间转世界空间 Unity5 5版本中 Object2World已经变成unity ObjectToWorld World2Object也变成了unity WorldToObject 但由于Unity的向下
  • Macos安装brew攻略

    Brew Macos的apt get和软件安装快捷方式 Brew install offiical site https brew sh install instruction bin bash c curl fsSL https raw
  • java批量插入数据库之写绑定变量

    最近查到关于sql批量写入和绑定变量的问题 看到了很多好的帖子 再次进行总结 数据库在执行SQL语句时会首先解析SQL语句 解析又分为硬解析与软解析 说到硬解析和软解析 就不能不说一下Oracle对sql的处理过程 当你发出一条sql语句交