JDBC与Statement和PreparedStatement的区别彩民之家高手

2019-09-20 06:10 来源:未知

最显明的分歧,就是实施的sql语句格式分歧。大家往上放两段代码来看看她们的界别把:

代码背景:大家有一个数据库,里面有一个user表,有username,userpwd两列。大家要得知这两列的数量。

那是运用CreateStatement方法创立了stmt对象,再经过他询问的一有个别语句片段。

String sql = "select * from users where  username= '" username "' and userpwd='" userpwd "'";
stmt = conn.createStatement();
rs = stmt.executeQuery(sql);

  而上边则是利用了PrepareStatement方法创设了pstmt对象,再通过这几个指标查询的一有个别语句片段。

String sql = "select * from users where  username=? and userpwd=?";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, username);
pstmt.setString(2, userpwd);
rs = pstmt.executeQuery();

  相信写到这,大家多两个人就能够看出来了,原本PrepareStatement跟Statement的基本点差距正是把地方sql语句中的变量抽取来了。那便是本人要说的率先大优点,PrepareStatement能够加强代码的可读性。

 

  3、Statement 与 PreparedStatement的区别(摘录自):

1.语法区别

Statement只协理静态编写翻译,SQL语句是写死的。

PreparedStatement协助预编译,用?号来占位。

2.效用分化

Statement每一次都要发送一条SQL语句,不补助缓存,实践功用低。

PreparedStatement支持预编写翻译,缓存在数据库,只需发送参数,实行功效快。

3.安全性分裂

Statement轻便被注入。

流入:狡滑的分子得以编写制定特殊的SQL语句来入侵数据库。

例如:要查询某些顾客的新闻

相似景况:SELECT * FROM user_list where username=xxx and password=xxx;(这里的xxx本应该为顾客填写本身的客户名和密码)

流入情状:SELECT * FROM user_list where username='abc' or 1=1 -- password=xxx;

那样1=1恒等,况兼在password前增进了“--”号,后边的从头到尾的经过成为了批注不被试行。相当于说,那样就能够不用密码地询问全数的客户消息。

PreparedStatement,因为规定了SQL语句中的参数,所以可避防卫流入。

jdbc中的Statement对象和Preparedstatement对象的界别,以及由此jdbc操作调用存款和储蓄进度,preparedstatement

一、

java.sql.*   和  javax.sql.*的包的类组织

 

                            |- Driver接口: 表示java驱动程序接口。全体的实际的数据库厂家要来达成此接口。

                                     |- connect(url, properties):  连接数据库的方式。

                                                        url: 连接数据库的U奥迪Q7L

                                                                 U揽胜L语法: jdbc切磋:数据库子左券://主机:端口/数据库

                                                                 user: 数据库的客商名

                                                                 password: 数据库客户密码

                            |- DriverManager类: 驱动处理器类,用于管理全数注册的驱动程序

                                     |-registerDriver(driver)  : 注册驱动类对象

                                     |-Connection getConnection(url,user,password);  获取连接对象

 

                            |- Connection接口: 表示java程序和数据库的连天对象。

                                               |- Statement createStatement() : 创建Statement对象

                                               |- PreparedStatement prepareStatement(String sql)  创建PreparedStatement对象

                                               |- CallableStatement prepareCall(String sql) 创建CallableStatement对象

 

                            |- Statement接口: 用于实践静态的sql语句

                                               |- int executeUpdate(String sql)  : 实践静态的更新sql语句(DDL,DML)

                                               |- ResultSet executeQuery(String sql)  :试行的静态的询问sql语句(DQL)

 

                                     |-PreparedStatement接口:用于推行预编译sql语句

                                                        |- int executeUpdate() : 试行预编写翻译的换代sql语句(DDL,DML)

                                                        |-ResultSet executeQuery()  : 试行预编写翻译的询问sql语句(DQL)

 

                                               |-CallableStatement接口:用于实行存款和储蓄进度的sql语句(call xxx)

                                                                 |-ResultSet executeQuery()  : 调用存款和储蓄进程的方式

 

 

                            |- ResultSet接口:用于封装查询出来的数据

                                               |- boolean next() : 将光标移动到下一行

                                               |-getXX() : 获取列的值

Statemetent对象推行的是静态SQL语句,而PreparedStatement对象施行的是预编译SQL语句,如上海体育场面,Statement对象实施executeUpdate(String sql)和executeQuery(String sql),而PreparedStatement 对象施行的是无参的executeUpdate()和executeQuery(),从那多个议程能够看来那五个目的的风味,正因为这么,PreparedStatement可防止范SQL语句注入,更安全,当然它的功用也越来越高级中学一年级些。

二、通过jdbc代码调用存款和储蓄进度

代码如下

              

package com.a_callrablestatement;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;

import org.junit.Test;

import com.util.DBUtil;

public class Demo1 {

public Connection conn = null;
public CallableStatement cs = null;
ResultSet rs = null;
String driverClass = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
String url = "jdbc:sqlserver://localhost:1433;DatabaseName=User";
String username = "sa";
String password = "qwer1234";
String sql = "exec pro_findById ? ";
public Demo1() {
// TODO Auto-generated constructor stub
}
@Test
public void test1()
{

try{
//注册驱动
Class.forName(driverClass);
//连接
conn = DriverManager.getConnection(url,username,password);
//得到prepareCall预编写翻译对象
cs = conn.prepareCall(sql);
//设置问号的占位符
cs.setInt(1,3);

rs = cs.executeQuery();
//打字与印刷结果
while(rs.next())
{
int id = rs.getInt("id");
String name = rs.getString("username");
String password = rs.getString("password");
String gender = rs.getString("gender");
String interest = rs.getString("interest");
System.out.println(id "," name "," password "," gender "," interest);
}
}catch(ClassNotFoundException e)
{
e.printStackTrace();
}catch(SQLException e)
{
e.printStackTrace();
}finally
{
DBUtil.close(conn,rs,cs);
}
}

@Test
public void test2()
{
sql ="exec pro_findNameById ?,?";
try{
//注册驱动
Class.forName(driverClass);
//连接
conn = DriverManager.getConnection(url,username,password);
//获得prepareCall预编写翻译对象
cs = conn.prepareCall(sql);
//设置问号的占位符的参数值
cs.setInt(1,3);
/**
* 1.参数一,表示要设置的参数地点
* 2.参数二,表示要回去的参数值类型 varchar(20)
*/
cs.registerOutParameter(2, Types.VARCHAR);
//实践操作,但不回来结果集,再次来到值在参数中,这里不得不用execute(),不可能用executeQuery(),那是在SQL Server二〇〇九中
cs.execute();

/**
* 预编译sql中参数的任务
*/
String name = cs.getString(2);
//打字与印刷结果
System.out.println(name);

}catch(ClassNotFoundException e)
{
e.printStackTrace();
}catch(SQLException e)
{
e.printStackTrace();
}finally
{
DBUtil.close(conn,rs,cs);
}
}

}

工具类

package com.util;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class DBUtil {

public DBUtil() {
// TODO Auto-generated constructor stub
}
public static void close(Connection conn,ResultSet rs,PreparedStatement ps )
{
try{
if(conn!=null)
{
conn.close();
}
if(rs!=null)
{
rs.close();
}
if(ps!=null)
{
ps.close();
}
}catch(SQLException e)
{
e.printStackTrace();
throw new RuntimeException(e);
}
}
}

1.test1()方法是调用未有重回值的积累进程

2,test2()方法是调用有重临值的存储进度

在调用有重返值的存放进度时,不可能使用executeQuery(),不然会报未有回去结果集的不当彩民之家高手论坛 1

而改为execute()方法后就足以得到平常的结果

test1()中的存款和储蓄进度代码

use [User]
go

create procedure pro_findById(@id int)
as
select * from [tb_user] where [email protected]
go

 

test2()中的存款和储蓄进程

use [User]
go
create procedure findNameById @id int,@name varchar(20)
as
select @name=username from tb_user where [email protected]
go

注:SQL server 2008和jdk 1.7 加eclipse ee 4.5

一、 java.sql.* 和 javax.sql.*的包的类组织 |- Dri...

  综上所述,计算如下:Statement每一回实践sql语句,数据库都要实行sql语句的编写翻译,最佳用于仅实行三次询问并再次回到结果的意况,成效抢先PreparedStatement.但存在sql注入危机。PreparedStatement是预编译实践的。在试行可变参数的一条SQL时,PreparedStatement要比Statement的频率高,因为DBMS预编写翻译一条SQL当然会比多次编写翻译一条SQL的作用高。安全性更加好,有效防护SQL注入的难题。对于数次重复推行的口舌,使用Prepared

 三、要点表明

本身的几点浅见,各位大大不喜勿喷。

一、概述

  本文首要介绍Java接连数据库的着力办法和手续,并对里面包车型客车几个要点进行简易表达。

Statement作用会更加高级中学一年级些。推行SQL语句是能够带参数的,并辅助批量实行SQL。由于应用了Cache机制,则预编写翻译的话语,就能放在Cache中,下一次试行同一的SQL语句时,则足以平素从Cache中收取来。

二、数据库访谈步骤

  在Java中总是数据库举办的拜候重要有以下多少个步骤:

  1. 加载数据库驱动
  2. 注册数据库驱动
  3. 建设构造到数据库的连日
  4. 做客数据库

  首先,要调用Class.ForName()加载并注册mysql驱动程序类,加载驱动程序驱动类后,须要登记驱动程序类的四个实例,DriverManager类担任管理驱动程序,那么些类提供了registerDriver()方法来注册驱动程序类的实例,何况我们无需亲自调用那些点子,因为Drive接口的驱动程序类都含有了静态代码块,在这一个代码块中会调用registerDriver()方法来注册本人的叁个实例。

  然后调用DriverManager类的getConnection方法成立到数据库的连天。在确立连接后,供给对数据库实行拜望。在java.sql包中定义了多少个接口:Statement、PrepareStatement和CallableStatement,分别对应分化的调用格局。在那之中:  

  Statement:用于试行静态的sql语句。

  PrepareStatement:从Statement接口继承而来,它的指标表示一条预编写翻译过的sql语句,通过调用Connection对象的prepareStatement()方法得到。

  CallableStatement:用于施行sql存款和储蓄过程,该接口从PrepareStatement接口传承而来,通过调用Connection对象的prepareCall()方法得到CallableStatement对象。

  完整的拜望数据库代码如下:

package com.test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class CreateDB
{
    public static void main(String[] args)
    {
        String url="jdbc:mysql://localhost:3306";
        String user="root";
        String password="281889";
        String driverclass="com.mysql.jdbc.Driver";//JDBC类名
        try
        {
            //加载JDBC驱动,当这个类被加载时,类加载器会执行该类的静态代码块从而注册驱动程序的一个实例
            Class.forName(driverclass);  

            //建立数据库的连接
            Connection conn=DriverManager.getConnection(url,user,password);

            //访问数据库
            Statement stmt=conn.createStatement();
            stmt.execute("use information_schema");
            int i=0;
            ResultSet rs1=stmt.executeQuery("SELECT * FROM information_schema.SCHEMATA where SCHEMA_NAME='student'");
            while(rs1.next())  //判断是否含有student数据库
                i  ;
            if(i==0)
                stmt.executeUpdate("create database student");

            stmt.executeUpdate("use student");

            int j=0;
            ResultSet rs2=stmt.executeQuery("select * from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='student' and TABLE_NAME='stuinfo' ");
            while(rs2.next()) //判断数据库中是否含有stuinfo表
                j  ;
            if(j==0)
                stmt.executeUpdate("create table stuinfo(sno INT not null primary key,name VARCHAR(50) not null,age int,sex VARCHAR(50))");

            stmt.addBatch("insert into stuinfo values(0420,'阿斌',25,'男')");
            stmt.executeBatch();
            stmt.close();
            stmt=null;
            conn.close();
            conn=null;
        } 
        catch (ClassNotFoundException e)
        {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        } 
        catch (SQLException e)
        {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        }
    }
}

  2.然后加载驱动,成立连接,获得Connection接口的的兑现指标,举例对象名称叫做conn。

4、判别mysql中是不是已存在某数据库:

  stmt.execute("use information_schema");
   int i=0;
   ResultSet rs1=stmt.executeQuery("SELECT * FROM information_schema.SCHEMATA where SCHEMA_NAME='student'");
   while(rs1.next())  //判断是否含有student数据库
      i  ;
   if(i==0)
     stmt.executeUpdate("create database student");

  3.然后再用conn对象去创立Statement的实例,方法是:Statement stmt = conn.creatStatement("SQL语句字符串");

  1、execute(String sql)、executeUpdate(String sql)和executeQuery(String sql)的区别:

  execute:试行回来多少个结果集的sql语句。

  Returns:true if the first result is a ResultSet object

       false if it is an update count or there are no results

  executeUpdate:执行类似insert、update或许delete的sql语句。

  Returns:(1) the row count for SQL Data Manipulation Language (DML) statements

        (2) 0 for SQL statements that return nothing     

   executeQuery:奉行钦定的sql语句,重回四个ResultSet对象,用于查看实践的结果。

   Returns:a ResultSet object that contains the data produced by the given query;``

  ps:executeQuery重临的ResultSet长久都不会为null

PreparedStatement: 数据库会对sql语句进行预编译,下次执行相同的sql语句时,数据库端不会再进行预编译了,而直接用数据库的缓冲区,提高数据访问的效率(但尽量采用
使用?号的方式传递参数),如果sql语句只执行一次,以后不再复用。
 从安全性上来看,PreparedStatement是通过?来传递参数的,避免了拼sql而出现sql注入的问题,所以安全性较好。
 在开发中,推荐使用 PreparedStatement

  2、ResultSet对象

  ResultSet对象以逻辑表格的样式封装了实践数据库操作的结果集,其目的保证了二个针对当前数据行的游标,初阶状态下游标在率先行在此之前,能够经过next()方法移动游标到下一行。

PreparedStatement pstmt  =  con.prepareStatement("UPDATE EMPLOYEES  SET name= ? WHERE ID = ?");
pstmt.setString(1, "李四");
pstmt.setInt(2, 1);
pstmt. executeUpdate();

  5、推断数据库中是还是不是已存在某表:

  int j=0;
   ResultSet rs2=stmt.executeQuery("select * from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='student' and TABLE_NAME='stuinfo' ");
   while(rs2.next()) //判断数据库中是否含有stuinfo表
      j  ;
   if(j==0)
      stmt.executeUpdate("create table stuinfo(sno INT not null primary key,name VARCHAR(50) not null,age int,sex VARCHAR(50))");

 

  

一、先来讲说,什么是java中的Statement:Statement是java实施数据库操作的三个第一格局,用于在早就确立数据库连接的底子上,向数据库发送要进行的SQL语句。具体步骤:

  Statement 对象用于将 SQL 语句发送到数据库中。实际上有二种 Statement 对象,它们都看作在给定连接上实践SQL语句的包容器:Statement、PreparedStatement(它从 Statement 继承而来)和CallableStatement(它从 PreparedStatement 承继而来)。它们都专项使用于发送特定类型的 SQL 语句:Statement 对象用于实践不带参数的归纳 SQL 语句;PreparedStatement 对象用于推行带或不带参数的预编写翻译 SQL 语句;CallableStatement 对象用于实施对数据库已囤积进度的调用。

二、

终极但也是最要紧的一个大大的比Statement好的长处,那就是平安!

您说吗?那还关安全吗事情,这小编给您一行代码,你来给自家说说那是干嘛的。

String sql = "select * from user where username= '" varname "' and userpwd='" varpasswd "'";
stmt = conn.createStatement();
rs = stmt.executeUpdate(sql);

  那是注解顾客名密码的,对啊。但倘若大家把'or '1' = 1'看成密码传进去,你猜猜会发出啥。

select * from user where username = 'user' and userpwd = '' or '1' = '1';

  开采了呢!那是个永真式,因为1恒久等于1。所以不管怎样都能博获得权力。哇。那就坏咯!那还不是最坏的,你再看!

String sql = "select * from user where username= '" varname "' and userpwd='" varpasswd "'";
stmt = conn.createStatement();
rs = stmt.executeUpdate(sql);

  依然是那行代码。这一次大家把'or '1' = 1';drop table book;当成密码传进去。哇!又坏了!本次直接把表给删了。但是,你假设用PrepareStatement的话就不会产出这种难点。你传入的那些多少根本不会跟原本的多寡有另外的错落有致,也不会产生这几个主题材料。

 

 对数据库实行增加和删除改查的长河中的通用的流水生产线:

  (1)创立Connection对象、SQL查询命令字符串;

  (2)对Connection对象传入SQL查询命令,获得PreparedStatement对象;

  (3)对PreparedStatement对象推行executeUpdate()或executeQurey()获得结果;

  (4)先后关闭PreparedStatement对象和Connection对象。

  可知,使用JDBC时,最常打交道的是Connection、PreparedStatement那多个类,以及select中的ResultSet类。查阅Java API手册能够领会其切实的含义和章程。

  下边援引的Java API的素材来自。

  

  Connection

java.sql  接口 Connection

富有一级接口:
Wrapper


public interface Connectionextends Wrapper

 

与特定数据库的三番五次(会话)。在接连内外文中实施 SQL 语句并回到结果。

Connection 对象的数据库能够提供描述其表、所支撑的 SQL 语法、存款和储蓄进程、此连接效能等等的信息。此消息是利用 getMetaData 方法赢得的。

 

  PreparedStatemnt

java.sql  接口 PreparedStatement

负有一级接口:
Statement, Wrapper

具有已知子接口:
CallableStatement


public interface PreparedStatementextends Statement

表示预编写翻译的 SQL 语句的指标。

SQL 语句被预编写翻译并存款和储蓄在 PreparedStatement 对象中。然后能够利用此指标往往急速地推行该语句。

 

常用方法

 boolean  execute()

          在此 PreparedStatement 对象中进行 SQL 语句,该语句能够是别的项目标 SQL 语句。

 ResultSet  executeQuery()

          在此 PreparedStatement 对象中实践 SQL 查询,并回到该查询生成的 ResultSet 对象。

 int  executeUpdate()

          在此 PreparedStatement 对象中试行 SQL 语句,该语句必需是一个SQL 数据操作语言(Data Manipulation Language,DML)语句,举个例子INSERT、UPDATE 或 DELETE 语句;或许是无重返内容的 SQL 语句,比方 DDL 语句。

  

  ResultSet

  

java.sql  接口 ResultSet

装有一流接口:
Wrapper

不无已知子接口:
CachedRowSet, FilteredRowSet, JdbcRowSet, JoinRowSet, RowSet, SyncResolver, WebRowSet


public interface ResultSetextends Wrapper

意味着数据库结果集的数据表,日常经超过实际施查询数据库的言语生成。

  那么CallableStatement扩大了PreparedStatement的接口,用来调用存款和储蓄进度,它提供了对于输入和输出参数的支撑,CallableStatement 接口还应该有对 PreparedStatement 接口提供的输入参数的sql查询的帮衬。

上边说说第二点优点。ParperStatement提升了代码的灵活性和实施功能。

PrepareStatement接口是Statement接口的子接口,他持续了Statement接口的具备作用。它重假设拿来解决大家选择Statement对象往往执行同八个SQL语句的频率难点的。ParperStatement接口的编写制定是在数据库匡助预编写翻译的景况下优先将SQL语句编写翻译,当数十次施行那条SQL语句时,能够直接试行编译好的SQL语句,这样就大大提升了前后相继的布帆无恙和施行功效。

 

  1.第一导入java.sql.*;这个包。

先说下这俩到底是干啥的吗。其实那俩干的活儿都无差别,正是创立了叁个对象然后去通过对象调用executeQuery方法来实行sql语句。说是CreateStatement和PrepareStatement的界别,但实际说的正是Statement和PrepareStatement的区分,相信我们在网络早就见到过相当多这上面包车型地铁材质和博客,作者在此处提几点,大家看来过的,就当重记念,没看到就当补充~下边最初评论他们的界别。

TAG标签: MySQL JAVA
版权声明:本文由彩民之家高手论坛发布于彩民之家高手论坛,转载请注明出处:JDBC与Statement和PreparedStatement的区别彩民之家高手