(八)Servlet就是这样-JDBC及相关

来源:互联网 发布:rrb400软件代号 编辑:程序博客网 时间:2024/05/22 14:51

Servlet读书笔记系列文《Servlet就是这样》第八篇:JDBC及相关

一、   数据库驱动、JDBC

       数据库厂商提供的用来操作数据库用的jar包就是数据库驱动。各个厂商如果提供各自的数据库驱动的话会导致开发人员学习成本太高,所以sun公司提供了一套数据库驱动应该遵循的接口规范,这套规范就叫做JDBC,本质上是很多的接口

       由于所有的数据库驱动都遵循JDBC规范,我们在学习和使用数据库时只要学习JDBC中的接口就可以了。

二、   JDBC快速入门

       *在数据库中建立好表

       *在程序中导入数据库驱动包

*备注:给比较急切的朋友附上完整代码

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.sql.Statement;

 

//import com.mysql.jdbc.Driver;

 

public class JDBCDemo1 {

      

       publicvoid connection(){

             

              ResultSetresultSet = null;

              Statementstatement = null;

              Connectionconnection = null;

             

              try{

                     //1.注册数据驱动

//                  DriverManager.registerDriver(newDriver());

                     Class.forName("com.mysql.jdbc.Driver");

                     //2.获取数据库连接

                     connection= DriverManager.getConnection("jdbc:mysql://localhost:3306/estore","root", "password");

                     //3.获取传输器对象

                     statement= connection.createStatement();

                     //4.利用传输器输sql语句到数据库中执行,获取结果集对象

                     resultSet=statement.executeQuery("select * from user");

                     //5.遍历结果集,获取查询结果

                     while(resultSet.next()){

                            Stringusername = resultSet.getString("username");

                            System.out.println(username);

                     }

              }catch (Exception e) {

                     e.printStackTrace();

              }finally {

                     if(resultSet!= null) {

                            try{

                                   resultSet.close();

                            }catch (SQLException e) {

                                   e.printStackTrace();

                            }finally {

                                   resultSet= null;

                            }

                     }

                     if(statement!= null) {

                            try{

                                   statement.close();

                            }catch (SQLException e) {

                                   e.printStackTrace();

                            }finally {

                                   statement= null;

                            }

                     }

                     if(connection!= null) {

                            try{

                                   connection.close();

                            }catch (SQLException e) {

                                   e.printStackTrace();

                            }finally {

                                   connection= null;

                            }

                     }

              }

             

       }

       publicstatic void main(String[] args) throws SQLException, ClassNotFoundException {

              JDBCDemo1jdbcHelper = new JDBCDemo1();

              jdbcHelper.connection();

       }

 

}

2.1、注册数据库驱动

l  第一种方式:

              DriverManager.registerDriver(new Driver());

缺点一:观察mysqlDriver源码发现此方法导致了数据库驱动被注册了两次。

缺点二:整个程序域mysql数据库驱动绑定增加了耦合性

l  第二种方式:

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

2.2、获取连接

connection = DriverManager.getConnection(url,user, password);

l  url的写法:

Ø  Oracle写法:jdbc:oracle:thin:@localhost:1521:sid

Ø  SqlServer—jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=sid

Ø  MySql—jdbc:mysql://localhost:3306/sid

l  url可以接的参数

Ø  user、password

Ø  useUnicode=true&characterEncoding=UTF-8

2.3、获取传输器对象

statement = connection.createStatement();

创建向数据库发送sql的statement对象。

statement = connection.prepareStatement(sql);

创建向数据库发送预编译sql的PrepareSatement对象。

2.4、利用传输器执行sql语句获取结果集

statement .executeQuery(String sql)

用于向数据发送查询语句。

statement .executeUpdate(String sql)

用于向数据库发送insert、update或delete语句

statement .execute(String sql)

用于向数据库发送任意sql语句

2.5、遍历结果集取出结构

ResultSet以表的样式在内存中保存了查询结果,其中还维护了一个游标,最开始的时候游标在第一行之前,每调用一次next()方法就试图下移一行,如果移动成功返回true;

ResultSet还提供了很多个Get方法,用来获取查询结果中的不同类型的数据

除了next方法,还有以下方法可以用来遍历结果集:

                     next():移动到下一行

                     Previous():移动到前一行

                     absolute(introw):移动到指定行

                     beforeFirst():移动resultSet的最前面。

                     afterLast():移动到resultSet的最后面。

2.6、释放资源

              conn是一个有限的资源,用完立即要释放掉

              stat占用内存,所以使用完后也要释放

              rs占用内存,所以使用完后也要释放

              释放时后创建的先释放

              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;

                     }

              }

三、   PreparedStatement

3.1、Sql注入:由于jdbc程序在执行的过程中sql语句在拼装时使用了由页面传入参数,如果用户恶意传入一些sql中的特殊关键字,会导致sql语句意义发生变化,这种攻击方式就叫做sql注入,参考用户注册登录案例。

3.2、PreparedStatement是Statement的孩子,不同的是,PreparedStatement使用预编译机制,在创建PreparedStatement对象时就需要将sql语句传入,传入的过程中参数要用?替代,这个过程回导致传入的sql被进行预编译,然后再调用PreparedStatement的setXXX将参数设置上去,由于sql语句已经经过了预编译,再传入特殊值也不会起作用了。

3.3、PreparedStatement使用了预编译机制,sql语句在执行的过程中效率比Statement要高。

四、   大数据

       1.mysql数据库也可以直至在数据库中保存大文本和大二进制数据,

              Text

              TINYTEXT(255)、TEXT(64k)、MEDIUMTEXT(16M)和LONGTEXT(4G)

              Blob

              TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB

       2.JDBC去操作大文本:

              ~插入大文本:

                     ps= conn.prepareStatement("insert into Demo2Text values(null,?,?)");

                     ps.setString(1,"钢铁是怎样练成");

                     Filefile = new File("1.txt");

                     ps.setCharacterStream(2,new FileReader(file), (int) file.length());

                            //1.Exceptionin thread "main" java.lang.AbstractMethodError:com.mysql.jdbc.PreparedStatement.setCharacterStream(ILjava/io/Reader;J)V

                                   //ps.setCharacterStream(2,new FileReader(file), file.length());第三个参数是long型的是从1.6才开始支持的,驱动里还没有开始支持。

                                   //解决方案:ps.setCharacterStream(2,new FileReader(file), (int)file.length());

                            //2.Exceptionin thread "main" java.lang.OutOfMemoryError: Java heap space

                                   //文件大小过大,导致PreparedStatement中数据多大占用内存,内存溢出

                                   //-Xms256M-Xmx256M

                            //3.com.mysql.jdbc.PacketTooBigException:Packet for query is too large (10886466 > 1048576). You can change thisvalue on the server by setting the max_allowed_packet' variable.

                                   //数据库连接传输用的包不够大,传输大文本时报此错误

                                   //在my.ini中配置max_allowed_packet指定包的大小

                     ~查询大文本:

                            Readerrd = rs.getCharacterStream("content");

              3.JDBC操作大二进制

              ~插入:

                     ps= conn.prepareStatement("insert into Demo3Blob values(null,?,?)");

                     ps.setString(1,"梦想的力量");

                     Filefile = new File("1.mp3");

                     ps.setBinaryStream(2,new FileInputStream(file), (int) file.length());

                    

              ~查询

                     InputStreamin = rs.getBinaryStream("content");

0 0