浅谈JDBC

来源:互联网 发布:管理孩子上网软件 编辑:程序博客网 时间:2024/06/01 15:24

一. 1. JDBC数据库的定义:JDBC (java data base connectivity ,java 数据库连接) 是一j种用于执行SQL语句的java api ,可以为多种关系数据库提供统一的访问规范,它由一组java编程语言写的类和接口组成.

 2,在没有出现jdbc之前,各个数据库生产厂家(mysql,Oracle)都有自己的数据库驱动,这样程序员在操作不同数据库的时候就需要对操作不同数据库的API进行学习,学习成本相当的高,因此SUN公司就退出了JDBC,统一了各种数据库的编程语言,因而方便通过统一的标准对数据库进行操作.

关系图如下:

     

 

3, 组成JDBC 的两个包:java.sql和javax.sql    在需要这两个包的同时还需要导入相应的JDBC的数据库实现(及数据库驱动  这是一些实现JDBC接口的实现类 mysql-connector-java-5.0.8-bin-jar  )

4, JDBC的快速入门:

         前期准备工作:1. 在数据库库中建立还好表;2. 在程序中导入数据库驱动包;

        1)注册数据库驱动:DriverManager.registerDriver(new Driver());//缺点一:观察mysqlDriver源码发现此方法导致了数据库驱动被注册了两次.

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

                                      Class.forName(“com.mysql.jdbc.Driver”);//可以从配置文件中获取所要注册的驱动.

2).获取连接
 DriverManager.getConnection(url, user, password);
 ~url的写法:

 
  Oracle写法:jdbc:oracle:thin:@localhost:1521:sid
  SqlServer—jdbc:microsoft:sqlserver://localhost:1433; DatabaseName=sid
  MySql—jdbc:mysql://localhost:3306/sid
 ~url可以接的参数
  user、password
  useUnicode=true&characterEncoding=UTF-8

 3).获取传输器
  createStatement():创建向数据库发送sql的statement对象。
  prepareStatement(sql) :创建向数据库发送预编译sql的PrepareSatement对象。
 4).利用传输器执行sql语句获取结果集
  executeQuery(String sql) :用于向数据发送查询语句。
  executeUpdate(String sql):用于向数据库发送insert、update或delete语句
  execute(String sql):用于向数据库发送任意sql语句

 5).遍历结果集取出结构
  ResultSet以表的样式在内存中保存了查询结果,其中还维护了一个游标,最开始的时候游标在第一行之前,每调用一次next()方法就试图下移一行,如果移动成功返回true;
  ResultSet还提供了很多个Get方法,用来获取查询结果中的不同类型的数据
  除了next方法,还有以下方法可以用来遍历结果集:
   next():移动到下一行
   Previous():移动到前一行
   absolute(int row):移动到指定行
   beforeFirst():移动resultSet的最前面。
   afterLast() :移动到resultSet的最后面。
 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;
   }
  }

5.eg.一个具体通过JDBC链接数据库,并进行select操作的实例:


  1. package cn.guoqing.JDBC;  
  2.   
  3. import java.sql.Connection;  
  4. import java.sql.DriverManager;  
  5. import java.sql.ResultSet;  
  6. import java.sql.Statement;  
  7. import org.junit.Test;  
  8.   
  9. public class JdbcDemo1 {  
  10.     @Test  
  11.     public void test1(){  
  12.           
  13.         Connection connection=null;  
  14.         Statement statement=null;  
  15.         ResultSet rs=null;  
  16.         try {  
  17.             //在mydb4数据库基础上创建一个tabel1表:create table tabe1(name varchar(20),age int,salary double);  
  18.             //1.注册驱动管理器(将一个具体操作数据库的驱动注册到驱动管理器上)   
  19.             //DriverManager.registerDriver(new Driver());//此方法实际上注册类两次管理器  (注册驱动管理器的第一种方式)  
  20.             Class.forName("com.mysql.jdbc.Driver");//注册驱动管理器的第二种方式  
  21.               
  22.             //2.获取链接数据库的connection对象   
  23.             connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb4""root""root");  
  24.             //3.获取向数据库传输数据的传输器   
  25.             statement = connection.createStatement();  
  26.             //4.利用传输器向数据库传输Sql语句,获取结果集(executeQueryy用于查询操作)  
  27.             rs = statement.executeQuery("select * from tabe1 where name='张三'");  
  28.             //5.遍历返回集中记录   
  29.                 while(rs.next()){  
  30.                     //下面的的两种方法返回的都是String类型的   
  31.                     String name=rs.getString("name");  
  32.                     String age = rs.getString(2);  
  33.                     System.out.println(name);  
  34.                     System.out.println(age);  
  35.                 }  
  36.         } catch (Exception e) {  
  37.               
  38.             e.printStackTrace();  
  39.         }  
  40.             //6.关闭操作数据的相关的资源(关闭相关资源的原则:先创建的后关闭,后创建的先关闭)  
  41.           
  42.         finally{  
  43.               
  44.             try{  
  45.                 if(rs!=null)  
  46.                     rs.close();  
  47.                   
  48.             }  
  49.             catch (Exception e) {  
  50.                 e.printStackTrace();  
  51.             }  
  52.             finally{  
  53.                 rs=null;  
  54.             }  
  55.               
  56.             try{  
  57.                 if(statement!=null)  
  58.                     statement.close();  
  59.             }  
  60.             catch (Exception e) {  
  61.                 e.printStackTrace();  
  62.             }  
  63.             finally{  
  64.                 statement=null;  
  65.             }  
  66.               
  67.               
  68.             try{  
  69.                 if(connection!=null)  
  70.                     connection.close();  
  71.                   
  72.             }  
  73.             catch (Exception e2) {  
  74.                 e2.printStackTrace();  
  75.             }  
  76.             finally{  
  77.                 connection=null;  
  78.             }  
  79.         }  
  80.           
  81.     }  
  82. }  

二.PreparedStatement:

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

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

3.Statement与PreparedStatement类的比较:

   

PreperedStatement可以避免SQL注入的问题。
Statement会使数据库频繁编译SQL,可能造成数据库缓冲区溢出。PreparedStatement 可对SQL进行预编译,从而提高数据库的执行效率。
并且PreperedStatement对于sql中的参数,允许使用占位符的形式进行替换,简化sql语句的编写

 

eg:  PreparedStatement类的实例:

1.config.properties配置文件:


  1. driver=com.mysql.jdbc.Driver  
  2. url=jdbc:mysql://localhost:3306/mydb4  
  3. user=root  
  4. password=root  

2.自定义的一个工具类:

[java] view plaincopyprint?
  1. package cn.guoqing.utils;  
  2.   
  3. import java.io.FileInputStream;  
  4. import java.sql.Connection;  
  5. import java.sql.DriverManager;  
  6. import java.sql.ResultSet;  
  7. import java.sql.Statement;  
  8. import java.util.Properties;  
  9.   
  10. public class Util {  
  11.     //本类需要设置为单例模式   
  12.     private Util() {};  
  13.       
  14.     //在类一加载的时候就在内存中创建,并将文件资源加载   
  15.     private static Properties prop = null;  
  16.     static {  
  17.   
  18.         try {  
  19.             prop = new Properties();  
  20.             prop.load(new FileInputStream("config.properties"));  
  21.   
  22.         } catch (Exception e) {  
  23.             e.printStackTrace();  
  24.             throw new RuntimeException();  
  25.         }  
  26.     }  
  27.     //获取连接数据库的connection对象   
  28.     public static Connection getConnection() {  
  29.         try {  
  30.             Class.forName(prop.getProperty("driver"));  
  31.             return DriverManager.getConnection(prop.getProperty("url"),  
  32.                     prop.getProperty("user"), prop.getProperty("password"));  
  33.         } catch (Exception e) {  
  34.   
  35.             e.printStackTrace();  
  36.             throw new RuntimeException();  
  37.         }  
  38.   
  39.     }  
  40.     //关闭操作数据库的相关的资源   
  41.     public static void close(Connection connection,Statement statement,ResultSet rs){  
  42.               
  43.             try{  
  44.                 if(rs!=null)  
  45.                     rs.close();  
  46.                   
  47.             }  
  48.             catch (Exception e) {  
  49.                 e.printStackTrace();  
  50.             }  
  51.             finally{  
  52.                 rs=null;  
  53.             }  
  54.               
  55.             try{  
  56.                 if(statement!=null)  
  57.                     statement.close();  
  58.             }  
  59.             catch (Exception e) {  
  60.                 e.printStackTrace();  
  61.             }  
  62.             finally{  
  63.                 statement=null;  
  64.             }  
  65.               
  66.               
  67.             try{  
  68.                 if(connection!=null)  
  69.                     connection.close();  
  70.                   
  71.             }  
  72.             catch (Exception e2) {  
  73.                 e2.printStackTrace();  
  74.             }  
  75.             finally{  
  76.                 connection=null;  
  77.             }  
  78.         }  
  79.           
  80. }  

 

[java] view plaincopyprint?
  1. package cn.guoqing.JDBC;  
  2.   
  3. import java.sql.Connection;  
  4. import java.sql.PreparedStatement;  
  5. import java.sql.ResultSet;  
  6. import java.sql.SQLException;  
  7.   
  8. import org.junit.Test;  
  9.   
  10. import cn.guoqing.utils.Util;  
  11.   
  12. public class PrepareStatementDemo1 {  
  13.     PreparedStatement statement =null;  
  14.     Connection connection =null;  
  15.     //利用prepareStatement() 方法对sql语句进行预编译处理防止发生sql注入安全  
  16.     @Test  
  17.     public void addTest(){  
  18.         try {  
  19.             //1,2, 注册获取connection对象   
  20.             connection = Util.getConnection();  
  21.               
  22.             //3, 获取PreparedStatemen   表示预编译的 SQL 语句的对象      
  23.             //在创建PreparedStatement对象时就需要将sql语句传入,传入的过程中参数要用?替代  
  24.             //这个过程回导致传入的sql被进行预编译,然后再调用PreparedStatement的setXXX将参数设置上去,  
  25.             //由于sql语句已经经过了预编译,再传入特殊值也不会起作用了。  
  26.             statement = connection.prepareStatement("insert into tabe1 values(?,?,?)");  
  27.                 //设置为设置的参数   
  28.             statement.setString(1,"雍正");  
  29.             statement.setInt(244);  
  30.             statement.setDouble(38000.00);  
  31.               
  32.             //4,执行查询语句   
  33.             int count = statement.executeUpdate();  
  34.             //5,判断sql语句执行的结果   
  35.             if(count>0){  
  36.                 System.out.println("插入语句执行成功! 影响的记录行数为:"+count);  
  37.             }  
  38.             else  
  39.                 System.out.println("sql语句执行失败");  
  40.               
  41.         } catch (SQLException e) {  
  42.             // TODO Auto-generated catch block   
  43.             e.printStackTrace();  
  44.         }  
  45.         finally{  
  46.             Util.close(connection, statement,null);  
  47.         }  
  48.     }  
  49. }  



三.大数据:

1.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, "致我们逝去的青春");
   File file = new File("1.txt");
   ps.setCharacterStream(2, new FileReader(file), (int) file.length());
    //1.Exception in 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.Exception in 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 this value on the server by setting the max_allowed_packet' variable.
     //数据库连接传输用的包不够大,传输大文本时报此错误
     //在my.ini中配置max_allowed_packet指定包的大小

       在MySql中的my.ini中主配置文件中具体的配置地方:

  

eg:  将一个大文本文件存储到数据库中和从数据库中取出的实例:


  1. package cn.guoqing.lob;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileReader;  
  5. import java.io.FileWriter;  
  6. import java.io.Reader;  
  7. import java.sql.Connection;  
  8. import java.sql.PreparedStatement;  
  9. import java.sql.ResultSet;  
  10. import java.sql.SQLException;  
  11.   
  12. import org.junit.Test;  
  13.   
  14. import cn.guoqing.utils.Util;  
  15.   
  16. public class ClobDemo {  
  17.     //处理文本数据类型的数据(数据量较大)   
  18.       
  19.     Connection connection=null;  
  20.     PreparedStatement statement=null;  
  21.     ResultSet rs =null;  
  22.     //向数据库中添加一个文本数据   
  23.     @Test  
  24.     public void add(){  
  25.         try {  
  26.               
  27.             connection=Util.getConnection();  
  28.           
  29.             statement = connection.prepareStatement("insert into books values(null,?,?)");  
  30.             statement.setString(1,"致我们逝去的青春");  
  31.             File file=new File("1.txt");  
  32.             statement.setCharacterStream(2,new FileReader(file),(int)file.length());  
  33.             int count = statement.executeUpdate();  
  34.             if(count>0){  
  35.                 System.out.println("插入操作成功,受影响的记录行数为:"+count);  
  36.             }  
  37.             else  
  38.                 System.out.println("插入失败");  
  39.         } catch (Exception e) {  
  40.             e.printStackTrace();  
  41.         }  
  42.         finally{  
  43.             Util.close(connection, statement, null);  
  44.         }  
  45.     }  
  46.       
  47.     //从数据库中获取文本本件   
  48.       
  49.     @Test  
  50.     public void get(){  
  51.           
  52.         try {  
  53.             connection= Util.getConnection();  
  54.             statement = connection.prepareStatement("select * from books where id=?");  
  55.             statement.setInt(11);  
  56.             rs = statement.executeQuery();  
  57.             while(rs.next()){  
  58.                 String bookname = rs.getString("name");  
  59.                 File file = new File(bookname+".txt");  
  60.                 FileWriter writer= new FileWriter(file);  
  61.                 Reader reader = rs.getCharacterStream("content");  
  62.                   
  63.                 char[] buf=new char[1024];  
  64.                 int len;  
  65.                 while((len=reader.read(buf))!=-1){  
  66.                     writer.write(buf, 0, len);  
  67.                 }     
  68.                 reader.close();  
  69.                 writer.close();  
  70.                   
  71.                       
  72.             }  
  73.         } catch (Exception e) {  
  74.               
  75.             e.printStackTrace();  
  76.         }  
  77.         finally{  
  78.             Util.close(connection, statement, rs);  
  79.         }  
  80.     }  
  81. }  


3.3.JDBC操作大二进制
  插入:
   ps = conn.prepareStatement("insert into Demo3Blob values(null,?,?)");
   ps.setString(1, "北京东路的日子.mp3");
   File file = new File("1.mp3");
   ps.setBinaryStream(2, new FileInputStream(file), (int) file.length());
   
  查询
   InputStream in = rs.getBinaryStream("content");

eg: 将一个大的二进制的文件存储到数据库中,和在数据库中将其取出的实例:


  1. package cn.guoqing.lob;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileInputStream;  
  5. import java.io.FileOutputStream;  
  6. import java.io.InputStream;  
  7. import java.sql.Connection;  
  8. import java.sql.PreparedStatement;  
  9. import java.sql.ResultSet;  
  10. import java.sql.SQLException;  
  11.   
  12. import org.junit.Test;  
  13.   
  14. import cn.guoqing.utils.Util;  
  15.   
  16. public class BlobDemo {  
  17.     //向数据库中添加一个MP3文件   
  18.     Connection connection=null;  
  19.     PreparedStatement statement =null;  
  20.     ResultSet rs=null;  
  21.     @Test  
  22.     public void add(){  
  23.         try {  
  24.             connection=Util.getConnection();  
  25.           
  26.             statement= connection.prepareStatement("insert into mymp3 values(null,?,?)");  
  27.             statement.setString(1"北京东路的日子.mp3");  
  28.             File file=new File("3.mp3");  
  29.             FileInputStream reader = new FileInputStream(file);  
  30.             statement.setBinaryStream(2, reader, (int)file.length());  
  31.             int count = statement.executeUpdate();  
  32.             if(count>0){  
  33.                 System.out.println("向数据库中存储mp3文件成功!");  
  34.             }  
  35.               
  36.         } catch (Exception e) {  
  37.             // TODO Auto-generated catch block  
  38.             e.printStackTrace();  
  39.         }  
  40.           
  41.     }  
  42.       
  43.     //通过jdbc从数据库中取出二进制数据,例如:MP3,MP4,电影等文件   
  44.     @Test  
  45.     public void getMp3(){  
  46.         try {  
  47.             connection=Util.getConnection();  
  48.       
  49.              statement = connection.prepareStatement("select * from mymp3 where id=?");  
  50.              statement.setInt(13);  
  51.                
  52.              rs= statement.executeQuery();  
  53.                
  54.              while(rs.next()){  
  55.                  String MP3name= rs.getString("name");  
  56.                  File file = new File(MP3name);  
  57.                 FileOutputStream fos = new FileOutputStream(file);  
  58.                 InputStream is = rs.getBinaryStream("content");  
  59.                 byte[] buf=new byte[1024];  
  60.                 int len=0;  
  61.                 while((len=is.read(buf))!=-1){  
  62.                       
  63.                     fos.write(buf, 0, len);  
  64.                 }  
  65.                 fos.close();  
  66.                 is.close();  
  67.              }  
  68.               
  69.         } catch (Exception e) {  
  70.             // TODO Auto-generated catch block   
  71.             e.printStackTrace();  
  72.         }  
  73.         finally{  
  74.             Util.close(connection, statement, rs);  
  75.         }  
  76.           
  77.           
  78.     }  
  79. }  

四.批处理

1.eg;


  1. package cn.guoqing.batch;  
  2.   
  3. import java.sql.Connection;  
  4. import java.sql.SQLException;  
  5. import java.sql.Statement;  
  6.   
  7. import javax.crypto.ExemptionMechanismSpi;  
  8.   
  9. import org.junit.Test;  
  10.   
  11. import cn.guoqing.utils.Util;  
  12.   
  13. /* 
  14.  * 批处理:第一种方式:没有使用预编译,而是用statament对象 
  15.  *      实现不同结构的sql语句的批处理方式 
  16.  * */  
  17. public class BatchDemo1 {  
  18.     Connection connection=null;  
  19.     Statement statement=null;  
  20.        
  21.     @Test  
  22.     public void batch1(){  
  23.           
  24.         try {  
  25.             //注册,获取connection对象   
  26.             connection=Util.getConnection();  
  27.             //获取传送器   
  28.             statement = connection.createStatement();  
  29.             //进行批处理:向传输器对象中输入不同的sql语句    
  30.             String sql1="create table table2(id int primary key auto_increment,name varchar(20),age int,salary double,birthday date)";  
  31.             String sql2="insert into table2 values(null,'雍正',32,10000.00,'998-01-10')";  
  32.             String sql3="insert into table2 values(null,'乾隆',42,12000.00,'198-04-15')";  
  33.             String sql4="insert into table2 values(null,'咸丰',54,10400.00,'1808-05-10')";  
  34.             String sql5="insert into table2 values(null,'溥仪',62,10800.00,'1888-09-23')";  
  35.               
  36.             statement.addBatch(sql1);  
  37.             statement.addBatch(sql2);  
  38.             statement.addBatch(sql3);  
  39.             statement.addBatch(sql4);  
  40.             statement.addBatch(sql5);  
  41.             //执行批处理命令   
  42.             int[] executeBatch = statement.executeBatch();  
  43.             //上面每条sql语句对记录的影响   
  44.             for(int i=0;i<executeBatch.length;i++){  
  45.                 System.out.println(executeBatch[i]);  
  46.             }  
  47.         } catch (Exception e) {  
  48.             // TODO Auto-generated catch block   
  49.             e.printStackTrace();  
  50.         }  
  51.         finally{  
  52.             Util.close(connection, statement, null);  
  53.         }  
  54.     }  
  55. }  

 2,eg:


  1. package cn.guoqing.batch;  
  2.   
  3. import java.sql.Connection;  
  4. import java.sql.PreparedStatement;  
  5. import java.sql.SQLException;  
  6. import java.sql.Statement;  
  7. import java.util.Date;  
  8.   
  9. import org.junit.Test;  
  10.   
  11. import cn.guoqing.utils.Util;  
  12.   
  13. /* 
  14.  * 批处理的第二种方式:通过利用批处理的方式 
  15.  *          应用:主要应用与对数据库的操作的sql语句的模式相同, 
  16.  *              而具体的参数内容不同 
  17.  *              例如:同时向数据库中添加多条记录的sql语句 
  18.  * */  
  19. public class BatchDemo2 {  
  20.     Connection connection=null;  
  21.     Statement statement=null;  
  22.     @Test   
  23.     public void batch2(){  
  24.           
  25.         try {  
  26.               
  27.             connection=Util.getConnection();  
  28.           
  29.             PreparedStatement statement = connection.prepareStatement("insert into table2 values(?,?,?,?,?)");  
  30.             for(int i=0;i<5;i++){  
  31.                 statement.setString(1null);  
  32.                 statement.setString(2,"张三"+i);  
  33.                 statement.setInt(320);  
  34.                 statement.setDouble(44000);  
  35.                 statement.setDate(5,new java.sql.Date(2000+i-1900,1+i,2+i));  
  36.                 statement.addBatch();  
  37.             }  
  38.             int[] executeBatch = statement.executeBatch();  
  39.   
  40.             if(executeBatch.length>0)  
  41.                 System.out.println("批处理成功");  
  42.             else  
  43.                 System.out.println("批处理失败!");  
  44.               
  45.             statement.clearBatch();  
  46.         } catch (SQLException e) {  
  47.             // TODO Auto-generated catch block  
  48.             e.printStackTrace();  
  49.         }  
  50.         finally{  
  51.             Util.close(connection, statement, null);  
  52.         }  
  53.     }  
  54. }  
原创粉丝点击