Statement 与 PreparedStatement 之争

    一直以来,有关Statement 与PreparedStatement 的争议主要的焦点在与性能上,但研究了oralce的jdbc驱动后(代码是通过jad对其进行反编译得到的,跟实际的有所差别),我自己都感慨个人所能感知的确实是太少了.

    由于公司自己用的框架对sql语句的处理都采用了独立于preparedstatement方式组装sql语句,然后再用preparedstatement执行execute,(有点好笑...最后都成一条无参数的语句了,为什么还是用preparedstatement执行,Statement 恐惧症?)而在其配置文件的解析类中对类型处理都采用string类型转换,如果插入的数据类型是string的话,则使用/'+参数+  /',如果是其他类型,则不加/',看起来似乎不会产生什么问题,但这样的做法我也怀疑了很久,它饶过了jdbc驱动提供了数据类型的设置,也就是set***()方法来设置参数。而使用了类似Statement.execute(String sql),无法提供类型的检查功能。除了类型检查外,用set***方法设置PreparedStatement 的sql语句参数与Statement 有差别吗??
    根据jdk对java.sql.Statement的描述,它是CallableStatement(存储过程), PreparedStatement的超级接口,也就是说,一旦实现了PreparedStatement,则Statement功能也会被继承.java.sql.*中的包,所有的接口由DriverManager通过管理jdbc的驱动类进行实现.而如果一个jdbc需要被引用或通过jvm连接到数据库,则就必须实现其必要的接口.
    在oracle的jdbc驱动中,(或许所有的jdbc驱动都是类似的)PreparedStatement实现set***方法都是将传入的参数(不管是int或string或其他类型)统一转换成byte[]字节,最后通过jvm将字节流通过tcp(在dirvier类导入了ServerTTC7Protocol和TTC7Protocol建立客户端和服务端的连接----如果是thin类型连接的话)方式传送.而对于oracle如何接收这些数据已经不是jdbc所能控制的了.对于非string 类型的数据,通过oracle.sql.NUMBER这个类的toBytes()进行转换,对与string类型的转换比较复杂(代码有200行或更多),但无论如何,所有传递的参数值都会被转换成与相同编码格式的byte字节流(应该是统一的utf-8编码).然后再传递给jvm,最后通过jvm把数据发送到oracle.

    对于Statement ,它并不能通过set***实现参数的设置,需要把要传递的内容全部写到一条sql语句中,这样,对于一些特殊的数据类型,如blob,clob或image等类型,是没办法传递的(你能想象下把一个有1m大的image转换成字节码作为传递参数写进sql语句的情况吗?),这是它的一个最大的缺点.虽然大多数情况,我们数据库不是存放文件或流的地方,而更关心的是他们在execute时的性能问题.

    这里我仍然不能确定Statement 与PreparedStatement 的性能优劣,这是与jdbc不同的驱动如何去实现他们两者是有关系的.在oracle14中,同样的查询,PreparedStatement 虽然继承了Statement ,但并没有在executeQuery时去调用Statement 的executeQuery方法,而是执行executeUpdate(),但默认的,最后他们都会执行doExecuteWithTimeout()方法(在Statement 中定义),而在前期,确实PreparedStatement 做的工作比Statement 多得多.--->它必须设置参数并进行编码转换,而对于Statement ,它只将一条sql语句进行了字符串转换.至于其中是否带来性能问题,只看查询的话,确实是Statement 好点(如果传递的sql语句不是很长的的话).

    如果是无传递参数的sql语句,使用PreparedStatement 会造成性能的损耗,因为当中,jdbc需要对该语句进行解析.

    jdbc驱动比较复杂,实在没心思也没那个精力深入研究了,具体的抉择,还是看个人的爱好了.
   

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值