JDBC_day01

来源:互联网 发布:免费网络电视 编辑:程序博客网 时间:2024/06/03 20:07

1  JDBC

1.1 JDBC概述

1.1.1   什么是JDBC?

JDBC( Java DataBase Connectivity ) 翻译过来就是Java数据库连接,其实就是通过Java语言操作数据库的一门技术。

 

由于数据库厂商提供的数据库驱动(操作数据库的jar包)各不相同,导致开发人员的学习成本十分的高。因此SUN公司提出了JDBC这套规范,用来统一访问数据的标准。JDBC本质上是一套接口,SUN要求所有的数据库厂商在设计驱动时,都要实现JDBC这套标准。因此开发人员只要学会JDBC这套接口,所有的数据库驱动就都会使用了。

1.1.2   为什么要学习JDBC?

在Java开发中,我们不是通过CMD窗口来操作数据库,更多的是通过Java程序来操作数据库,而JDBC就可以实现这样一个操作.

1.1.3    如何使用JDBC开发程序?

Ø  提出需求:

创建一个 jt_db 数据库,在库中创建一个Account表,并插入三条记录,然后利用Java程序查询出Account表中所有的记录,并打印在控制台上.

Ø  开发步骤:

(1) 准备数据

drop database if existsjt_db;

create database jt_db;

use jt_db;

create table account(

    id int primary key auto_increment,

    name varchar(50),

    money double

);

insert into accountvalues(null, 'tom', 1000);

insert into accountvalues(null, 'andy', 1000);

insert into accountvalues(null, 'tony', 1000);

(2) 创建工程

(3) 导入jar包

(4) 创建类并实现JDBC程序(六个步骤)

 

//1.注册数据库驱动

DriverManager.registerDriver(newDriver());

      

//2.获取数据库连接

Connection conn =DriverManager.getConnection("jdbc:mysql://localhost:3306/jt_db", "root","root");

 

//3.获取传输器

Statement stat =conn.createStatement();

      

//4.利用传输器发送SQL到数据库执行,并返回执行结果

ResultSet rs =stat.executeQuery("select * from account");

      

//5.打印结果

while (rs.next()) {

    int id = rs.getInt("id");

    String name = rs.getString("name");

    double money = rs.getDouble("money");

    System.out.println(id+" : "+name+" :"+money);

}

      

//6.释放资源

rs.close();

stat.close();

conn.close();

 

 

Ø  执行结果:

 

1.2 JDBC API详解

1.2.1    注册数据库驱动

DriverManager.registerDriver(newDriver());

 

真正在实际开发中,我们一般不会使用DriverManager.registerDriver(newDriver()); 这种方式注册驱动, 因为这种方式注册驱动有两个问题:

问题1:这种方式注册驱动会导致驱动注册两次

问题2:这种方式将程序和具体的数据驱动绑死在了一起。

 

因此我们在开发中其实是通过下面的方式来注册驱动,:

Class.forName(“com.mysql.jdbc.Driver”);

 

这种方式就可以解决上面的两个问题:

(1) 这种方式只会导致驱动注册一次(查看mysql的Driver类的源码可得知)

(2) 这种方式只是和数据库驱动类的全路径名字符串绑死在了一起,而这个字符串后期可以提取到配置文件中,因此第二个问题也得到了解决.

 

1.2.2    获取数据库连接

Connection conn = DriverManager.getConnection(“jdbc:mysql://localhost:3306/jt_db”,“root”, “root”);

Ø  数据库的的URL

数据库的url用于指定访问哪一个位置上的数据库服务器及服务器中的哪一个数据库,其写法为:

jdbc:mysql://localhost:3306/jt_db

----------  -------------- -----

协议名        主机名+端口   数据库的名字

     其简写形式为:

jdbc:mysql:///jt_db

 

Ø  Connection连接对象

Connection连接对象是JDBC程序中最重要的一个对象,上面提供了一些常用的方法.

createStatement(); -- 返回Statement传输器对象.

prepareStatement(); -- 返回PreparedStatement传输器对象

 

1.2.3   获取传输器

Statement stat = conn.createStatement();

 

Ø  Statement

Statement传输器对象用于向数据库服务器发送sql语句,该对象上提供一些常用的发送sql的方法.

 

executeQuery(Stringsql) – 用于向数据库发送查询类型的sql语句

executeUpdate(String sql)– 用于向数据库发送更新(增加、删除、修改)类型的sql语句

 

1.2.4   ResultSet结果集对象

ResultSet对象用于封装sql语句查询的结果. 也是一个非常重要的对象. 该对象上提供了一些遍历数据及获取数据的方法.

Ø  遍历数据行的方法

next() – 使指向数据行的索引向下移动一行

preview() – 使用指向数据行的索引向上移动一行

...

 

Ø  获取数据的方法

getInt(int columnName)

getInt(String columnLable)

getString(intcolumnName)

getString(StringcolumnLable)

getLong(intcolumnName)

getLong(StringcolumnLable)

...

 

1.2.5   释放资源

此处释放资源必须按照一定的顺序释放,越晚获取的越先关闭. 所以先关闭ResultSet对象,再关闭Statement对象,最后关闭Connection对象

另,为了避免上面的程序抛出异常,但是释放资源的代码不会执行,应该把释放资源的代码放在finally中 .

try{

    ...

}catch(Exception e){

    ...

}finally{

    if (rs != null) {

       try {

           rs.close();

       } catch (SQLException e) {

           e.printStackTrace();

       } finally {

           rs = null;

       }

    }

    if (stat != null) {

       try {

           stat.close();

       } catch (SQLException e) {

           e.printStackTrace();

       } finally {

           stat = null;

       }

    }

    if (conn != null) {

       try {

           conn.close();

       } catch (SQLException e) {

           e.printStackTrace();

       } finally {

           conn = null;

       }

    }

}

1.3 JDBC增删改查

课堂练习: 使用JDBC完成对account表的增删改查操作.

代码略...

1.4 JDBCUtils工具类的实现

需求分析:

通过上面的对account表增删改查的练习,我们可以发现,程序中出现了大量重复的代码,例如:获取连接以及最后释放资源。为了提高代码的复用,这里我们可以提供一个JDBCUtils 工具类,用来封装 JDBC程序中的一些重复的代码。

 

实现步骤:

(1)   创建一个 JDBCUtils 类,并提供私有构造方法,防止对此类进行实例化

(2)   提供 getConnection方法,用于获取数据库连接对象

(3)   提供 close 方法,用于释放资源

 

1.5 PreparedStatement对象

在上面的增删改查的操作中,使用的是Statement传输器对象,而在开发中我们用的更多的传输器对象是PreparedStatement对,PreparedStatement是Statement的子接口,比Statement更加安全,并且能够提高程序执行的效率。

1.5.1   模拟用户登陆案例

(1)   准备数据

use mydb1;

create table user(

    id intprimary key auto_increment,

    usernamevarchar(50),

    passwordvarchar(50)

);

insert into user values(null,'张三','123');

insert into user values(null,'李四','234');

(2)创建LoginDemo 类,提供 main 方法和 login 方法。

 

执行时,输入:

或输入

 

1.5.2   SQL注入攻击

通过上面的案例,我们发现在执行时,不输入密码只输入用户名也可以登陆成功。这就是SQL注入攻击。

 

SQL注入攻击:由于后台的SQL语句是拼接而来的。其中的参数是由用户提交的,如果用户在提交参数时,在其中掺杂了一些SQL关键字或者特殊符号,就可能会导致SQL语句的骨架发生变化。从而发生一些意外的情况。

 

如果防止SQL注入攻击? 使用PreparedStatement对象来替代Statement对象。

添加 loginByPreparedSatement方法,使用 PreparedStatement 来代替Statement作为传输器对象使用!

1.5.3   使用PreparedStatement对象的优势

(1) 可以防止SQL注入攻击

采用预编译机制,提前将SQL语句的骨架发送给数据库编译并确定下来,一旦SQL语句的骨架被确定,那么再次发送的就只能是SQL语句的参数,如果参数中再包含影响SQL骨架的关键字或者特殊符号。也只会被当作普通的文本来处理。

(2) 省去了拼接SQL语句的麻烦

(3) 能够尽最大可能提高程序执行的效率

通过PreparedStatement对象发送sql的骨架到数据库会先进行编译,编译之后的SQL会被缓存下来,如果下次执行的sql骨架和上次相同,则无需在编译而是直接使用上次的缓存,可以减少SQL语句编译的次数,提高程序的执行效率。

使用Statement对象发送的sql语句到数据库之后虽然也会编译,但是由于Statement对象发送的sql是先拼接好,在发送给数据库,如果骨架相同但是每次执行的参数不同,整条sql语句也就不相同,所以每次都需要编译。

 

原创粉丝点击