java数据库连接(一)--从最简单地jdbc连接说起

  JDBCJDBC全称"Java DataBase Connectivity",它是一套面向对象的应用程序接口(API),并且制定了统一的访问各类关系数据库的标准接口,为各个数据库厂商提供了标准的接口实现。通过使用JDBC技术,开发人员可以用纯Java语言和标准的SQL语句编写完整的数据库应用程序,真正地实现软件的跨平台。

       java数据库连接(一)--从最简单地jdbc连接说起

        本文地址:http://blog.****.net/chen_zw/article/details/18514723

       JDBC对多种关系型数据库的驱动和操作都进行了封装,因此,开发者不需要编写额外的程序来兼容不同的数据库连接,只需要通过加载不同的数据库驱动程序即可完成连接,我们首先简单地封装JDBC连接类:

[java] view plain copy
 java数据库连接(一)--从最简单地jdbc连接说起java数据库连接(一)--从最简单地jdbc连接说起
  1. import java.sql.Connection;  
  2. import java.sql.DatabaseMetaData;  
  3. import java.sql.DriverManager;  
  4. import java.sql.ResultSet;  
  5. import java.sql.SQLException;  
  6. import java.sql.Statement;  
  7.   
  8. import oracle.jdbc.driver.OracleConnection;  
  9.   
  10. /** 
  11.  * @Description: JDBC连接类(示例连接Oralce) 
  12.  * @CreateTime: 2014-1-19 下午9:46:44 
  13.  * @author: chenzw  
  14.  * @version V1.0 
  15.  */  
  16. public class JdbcUtil {  
  17.     //驱动名    
  18.     private static String DRIVER = "oracle.jdbc.driver.OracleDriver";    
  19.     //获得url    
  20.     private static String URL = "admin";    
  21.     //获得连接数据库的用户名    
  22.     private static String USER = "jdbc:oracle:thin:@localhost:7001:test";    
  23.     //获得连接数据库的密码    
  24.     private static String PASS = "";    
  25.   
  26.     static {    
  27.         try {     
  28.             //1.初始化JDBC驱动并让驱动加载到jvm中,加载JDBC驱动后,会将加载的驱动类注册给DriverManager类。  
  29.             Class.forName(DRIVER);    
  30.         } catch (ClassNotFoundException e) {    
  31.             e.printStackTrace();    
  32.         }    
  33.     }    
  34.       
  35.      public static Connection getConnection(){    
  36.         Connection conn = null;    
  37.         try {     
  38.             //2.取得连接数据库    
  39.             conn = DriverManager.getConnection(URL,USER,PASS);    
  40.             //3.开启自动提交  
  41.             conn.setAutoCommit(true);  
  42.         } catch (SQLException e) {    
  43.             e.printStackTrace();    
  44.         }    
  45.         return conn;    
  46.      }    
  47.   
  48.     //开启事务  
  49.     public static void beginTransaction(Connection conn) {    
  50.         if (conn != null) {    
  51.             try {    
  52.                 if (conn.getAutoCommit()) {    
  53.                     conn.setAutoCommit(false);    
  54.                 }    
  55.             } catch (SQLException e) {    
  56.                 e.printStackTrace();    
  57.             }    
  58.         }    
  59.     }    
  60.     
  61.     //提交事务  
  62.     public static void commitTransaction(Connection conn) {    
  63.         if (conn != null) {    
  64.             try {    
  65.                 if (!conn.getAutoCommit()) {    
  66.                     conn.commit();    
  67.                 }    
  68.             } catch (SQLException e) {    
  69.                 e.printStackTrace();    
  70.             }    
  71.         }    
  72.     }    
  73.     
  74.     //回滚事务  
  75.     public static void rollBackTransaction(Connection conn) {    
  76.         if (conn != null) {    
  77.             try {    
  78.                 if (!conn.getAutoCommit()) {    
  79.                     conn.rollback();    
  80.                 }    
  81.             } catch (SQLException e) {    
  82.                 e.printStackTrace();    
  83.             }    
  84.         }    
  85.     }    
  86.       
  87.      //关闭连接  
  88.      public static void close(Object o){    
  89.         if (o == null){    
  90.             return;    
  91.         }    
  92.         if (o instanceof ResultSet){    
  93.             try {    
  94.                 ((ResultSet)o).close();    
  95.             } catch (SQLException e) {    
  96.                 e.printStackTrace();    
  97.             }    
  98.         } else if(o instanceof Statement){    
  99.             try {    
  100.                 ((Statement)o).close();    
  101.             } catch (SQLException e) {    
  102.                 e.printStackTrace();    
  103.             }    
  104.         } else if (o instanceof Connection){    
  105.             Connection c = (Connection)o;    
  106.             try {    
  107.                 if (!c.isClosed()){    
  108.                     c.close();    
  109.                 }    
  110.             } catch (SQLException e) {    
  111.                 e.printStackTrace();    
  112.             }    
  113.         }      
  114.     }    
  115.   
  116.     //重载关闭连接  
  117.     public static void close(ResultSet rs, Statement stmt,     
  118.             Connection conn){    
  119.         close(rs);    
  120.         close(stmt);    
  121.         close(conn);    
  122.     }    
  123.     //重载关闭连接  
  124.     public static void close(ResultSet rs,     
  125.             Connection conn){    
  126.         close(rs);     
  127.         close(conn);    
  128.     }   
  129.     //重载关闭连接  
  130.     public static void close(ResultSet rs, PreparedStatement ps,     
  131.             Connection conn){    
  132.         close(rs);    
  133.         close(ps);    
  134.         close(conn);    
  135.     }    
  136. }  

        JDBC数据库连接的查询主要通过Statement对象来执行各种SQL语句。Statement对象主要分为以下3种类型:

      1. Statement :执行静态SQL语句的对象。

             Statement接口常用的2个方法:

             (1) executeUpdate(String sql) :执行insert / update / delete 等SQL语句,成功返回影响数据库记录行数的int整数型。

             (2) executeQuery(String sql) : 执行查询语句,成功返回一个ResultSet类型的结果集对象。

[java] view plain copy
 java数据库连接(一)--从最简单地jdbc连接说起java数据库连接(一)--从最简单地jdbc连接说起
  1. ResultSet rs = null;  
  2. Statement stmt = null;  
  3. try {  
  4.     stmt = conn.createStatement();  
  5.     int num = stmt.executeUpdate("insert into company values('No.1','****')");  
  6.     rs = stmt.executeQuery("select * from company");  
  7. catch (SQLException e) {  
  8.     // TODO Auto-generated catch block  
  9.     e.printStackTrace();  
  10.         conn.rollback();  
  11. }finally{  
  12.     JdbcUtil.close(rs, stmt, conn);  
  13. }  

         1.1 Statement批量处理函数:

               (1) addBatch(String sql) :添加批量处理的数据;

               (2) executeBatch():提交批量数据;

               (3) clearBatch():清空已添加的批量数据;

[java] view plain copy
 java数据库连接(一)--从最简单地jdbc连接说起java数据库连接(一)--从最简单地jdbc连接说起
  1. /** 
  2.   * 实验一:Statement.executeBatch(); 
  3.   */  
  4. ResultSet rs = null;  
  5. Statement stmt = null;  
  6. try {  
  7.     conn.setAutoCommit(false); //切记:必须设置成手动提交模式,否则每次addBatch都会提交一次,而不是批量提交  
  8.     stmt = conn.createStatement();  
  9.     Long startMemory  = Runtime.getRuntime().freeMemory();  
  10.     Long startTime = System.currentTimeMillis();   
  11.     for(int i = 0; i < 10000; i++){  
  12.         stmt.addBatch("insert into t_dept values('No.1','****')");  
  13.         //stmt.executeUpdate("insert into t_dept values('No.1','****')");  
  14.     }  
  15.     stmt.executeBatch();  
  16.     conn.commit();  
  17.     Long endMemory = Runtime.getRuntime().freeMemory();  
  18.     Long endTime = System.currentTimeMillis();   
  19.     System.out.println("使用内存大小:"+ (startMemory-endMemory)/1024 + "KB");  
  20.     System.out.println("用时:"+ (endTime-startTime)/1000 + "s");  
  21. catch (SQLException e) {  
  22.     e.printStackTrace();  
  23.     conn.rollback();  
  24. }finally{  
  25.     JdbcUtil.close(rs, stmt, conn);  
  26. }  
  27.   
  28. //执行结果:  
  29. 使用内存大小:488KB  
  30. 用时:116s   --汗,原谅我的电脑龟速。  
[java] view plain copy
 java数据库连接(一)--从最简单地jdbc连接说起java数据库连接(一)--从最简单地jdbc连接说起
  1. /** 
  2.   * 实验二:Statement.executeUpdate(); 
  3.   */  
  4. //而如果直接使用executeUpdate更新(其实一样是批量提交),竟然比executeBatch速度更快,效率更高,这个真的百思不得其解,留待以后解决。。  
  5. ResultSet rs = null;  
  6. Statement stmt = null;  
  7. try {  
  8.     conn.setAutoCommit(false); //切记:必须设置成手动提交模式,否则每次addBatch都会提交一次,而不是批量提交  
  9.     stmt = conn.createStatement();  
  10.     Long startMemory  = Runtime.getRuntime().freeMemory();  
  11.     Long startTime = System.currentTimeMillis();   
  12.     for(int i = 0; i < 10000; i++){  
  13.             //stmt.addBatch("insert into t_dept values('No.1','****')");  
  14.         stmt.executeUpdate("insert into t_dept values('No.1','****')");  
  15.     }  
  16.     //stmt.executeBatch();  
  17.     conn.commit();  
  18.     Long endMemory = Runtime.getRuntime().freeMemory();  
  19.     Long endTime = System.currentTimeMillis();   
  20.     System.out.println("使用内存大小:"+ (startMemory-endMemory)/1024 + "KB");  
  21.     System.out.println("用时:"+ (endTime-startTime)/1000 + "s");  
  22. catch (SQLException e) {  
  23.     e.printStackTrace();  
  24.     conn.rollback();  
  25. }finally{  
  26.     JdbcUtil.close(rs, stmt, conn);  
  27. }  
  28. //执行结果:  
  29. <span style="font-family: Arial, Helvetica, sans-serif;">使用内存大小:329KB</span>  
  30. 用时:98s  
Note:本次实验得出的结论是使用executeUpdate的批量提交法比executeBatch效率高,速度更快,占用内存更小,如果有朋友有不同结论的话,欢迎留言交流。

       1.3 Statement可滚动ResultSet配置:

              (1) java.sql.Connection.creatStatement(int resultSetType,int resultSetConcurrency);

              (2) java.sql.Connection.creatStatement(int resultSetType,int resultSetConcurrency,int resultSetHoldability);

              参数:

              [1] resultSetType: -- 生成的ResultSet的类型

                   ResultSet.TYPE_FORWARD_ONLY  -- 结果集只允许向前滚动,默认缺省值

                   ResultSet.TYPE_SCROLL_INSENSITIVE  --  结果集对数据库中的的数据变动是不敏感的

                   ResultSet.TYPE_SCROLL_SENSITIVE  --  结果集对数据库中的的数据变动是敏感的(实际上只对Update的数据敏感)

                  Note:ResultSet为TYPE_SCROLL_INSENSITIVE时,我们取出的是数据库中真实数据,并且保存在内存中,一旦取出后,数据库中数据进行变动将不能及时更新到ResultSet中; 而ResultSet为TYPE_SCROLL_SENSITIVE时,我们取出的是数据库中数据的索引值(类似于rowid),每次rs.next()时将根据该索引时重新从数据库中取出数据,所以说是敏感的,但是如果数据库中进行的是添加或是删除操作,那敏感性也将无效。(自己思考,索引值)

              [2] resultSetConcurrency: -- 生成的ResultSet的并发性(指定是否可修改ResultSet结果集)

                    ResultSet.CONCUR_READ_ONLY  -- 结果集不可修改(只读),默认缺省值

                    ResultSet.CONCUR_UPDATABLE  -- 结果集可修改

[java] view plain copy
 java数据库连接(一)--从最简单地jdbc连接说起java数据库连接(一)--从最简单地jdbc连接说起
  1. ResultSet rs = null;  
  2. Statement stmt = null;  
  3. try {  
  4.     stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY);  //可滚动,  
  5.         rs = stmt.executeQuery("select * from staff");  
  6.         System.out.println(rs.isBeforeFirst()); //true,判断指针是否在结果集的开头  
  7.     rs.beforeFirst(); //指针定位到开头,该行取不到数据  
  8.     rs.next(); //必须先把指针移到数据上,才算是结果集的第一行  
  9.         System.out.println(rs.isFirst()); //true,判断指针是否在结果集的第一行  
  10.     rs.first();   //指针重新定位到结果集的第一行  
  11.     rs.absolute(20);  //指针定位到结果集的第20行  
  12.     rs.previous();  //指针移动到上一行  
  13.     System.out.println(rs.getString(1));  
  14.     rs.last(); //指针定位到结果集的最后一行  
  15.     System.out.println(rs.isLast());  //true,判断指针是否在结果集最后一行  
  16.     rs.afterLast(); //指针定位到末尾,该行取不到数据  
  17.         System.out.println(rs.isAfterLast()); //true,判断指针是否在结果集的末尾  
  18. catch (SQLException e) {  
  19.     e.printStackTrace();  
  20.     conn.rollback();  
  21. }finally{  
  22.     JdbcUtil.close(rs, stmt, conn);  
  23. }   <span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">             </span>  

      2. PrepareStatement: 执行预编译SQL语句对象。

             PrepareStatement接口常用的2个方法:

             (1) executeUpdate(String sql) :执行insert / update / delete 等SQL语句,成功返回影响数据库记录行数的int整数型。

             (2) executeQuery(String sql) : 执行查询语句,成功返回一个ResultSet类型的结果集对象。

[java] view plain copy
 java数据库连接(一)--从最简单地jdbc连接说起java数据库连接(一)--从最简单地jdbc连接说起
  1. ResultSet rs = null;  
  2. PreparedStatement ps;  
  3. try {  
  4.     ps = conn.prepareStatement("insert into company values(?,?)");  
  5.     ps.setString(1"No1.");  
  6.     ps.setString(2"****");  
  7.     int num = ps.executeUpdate();  
  8. catch (SQLException e) {  
  9.     // TODO Auto-generated catch block  
  10.     e.printStackTrace();  
  11.         conn.rollback();  
  12. }finally{  
  13.     JdbcUtil.close(rs, stmt, conn);  
  14. }  
  15.           
  16. try {  
  17.     ps = conn.prepareStatement("select * from company");  
  18.     ps.setString(1"No1.");  
  19.     ps.setString(2"****");  
  20.     rs = ps.executeQuery();  
  21. catch (SQLException e) {  
  22.     // TODO Auto-generated catch block  
  23.     e.printStackTrace();  
  24.         conn.rollback();  
  25. }finally{  
  26.     JdbcUtil.close(rs, stmt, conn);  
  27. }  

              优点:(1)可以有效SQL注入式攻击,提高安全性。(2)使用预处理语句在性能上提升很多。

         2.1 PrepareStatement批量处理函数:

               (1) addBatch(String sql) :添加批量处理的数据;

               (2) executeBatch():提交批量数据;

               (3) clearBatch():清空已添加的批量数据;

[java] view plain copy
 java数据库连接(一)--从最简单地jdbc连接说起java数据库连接(一)--从最简单地jdbc连接说起
  1. /** 
  2.   * 实验三:PreparedStatement.executeBatch(); 
  3.   */  
  4. ResultSet rs = null;  
  5. PreparedStatement ps = null;  
  6. try {  
  7.     conn.setAutoCommit(false); //切记:必须设置成手动提交模式,否则每次addBatch都会提交一次,而不是批量提交  
  8.     Long startMemory  = Runtime.getRuntime().freeMemory();  
  9.     Long startTime = System.currentTimeMillis();   
  10.     ps = conn.prepareStatement("insert into t_dept values(?,?)");  
  11.     for(int i = 0 ; i < 10000; i++){  
  12.         ps.setString(1"No1.");  
  13.         ps.setString(2"****");  
  14.         ps.addBatch();  
  15.         //ps.executeUpdate();  
  16.     }  
  17.     ps.executeBatch();  
  18.     conn.commit();  
  19.     Long endMemory = Runtime.getRuntime().freeMemory();  
  20.     Long endTime = System.currentTimeMillis();   
  21.     System.out.println("使用内存大小:"+ (startMemory-endMemory)/1024 + "KB");  
  22.     System.out.println("用时:"+ (endTime-startTime)/1000 + "s");  
  23. catch (SQLException e) {  
  24.     // TODO Auto-generated catch block  
  25.     e.printStackTrace();  
  26. }finally{  
  27.     JdbcUtil.close(rs, ps, conn);  
  28. }  
  29.   
  30. //执行结果:  
  31. 使用内存大小:2110KB  
  32. 用时:0s  --无语了,实在太快了,10000条。。。  
[java] view plain copy
 java数据库连接(一)--从最简单地jdbc连接说起java数据库连接(一)--从最简单地jdbc连接说起
  1. /** 
  2.   * 实验四:PreparedStatement.executeUpdate(); 
  3.   */  
  4. //直接使用executeUpdate批量提交,速度慢的可怕。。  
  5. ResultSet rs = null;  
  6. PreparedStatement ps = null;  
  7. try {  
  8.      conn.setAutoCommit(false); //切记:必须设置成手动提交模式,否则每次addBatch都会提交一次,而不是批量提交  
  9.      Long startMemory  = Runtime.getRuntime().freeMemory();  
  10.      Long startTime = System.currentTimeMillis();   
  11.      ps = conn.prepareStatement("insert into t_dept values(?,?)");  
  12.      for(int i = 0 ; i < 10000; i++){  
  13.          ps.setString(1"No1.");  
  14.          ps.setString(2"****");  
  15.          //ps.addBatch();  
  16.          ps.executeUpdate();  
  17.      }  
  18.      //ps.executeBatch();  
  19.      conn.commit();  
  20.      Long endMemory = Runtime.getRuntime().freeMemory();  
  21.      Long endTime = System.currentTimeMillis();   
  22.      System.out.println("使用内存大小:"+ (startMemory-endMemory)/1024 + "KB");  
  23.      System.out.println("用时:"+ (endTime-startTime)/1000 + "s");  
  24. catch (SQLException e) {  
  25. // TODO Auto-generated catch block  
  26.      e.printStackTrace();  
  27. }finally{  
  28.      JdbcUtil.close(rs, ps, conn);  
  29. }  
  30.   
  31. //执行结果:  
  32. 使用内存大小:1617KB  
  33. 用时:190s  --内存占用少了点,但是时间嘛,我只能说呵呵。。  
总结:使用批量提交数据一定要选用预编译的executeBatch()方法,虽然内存占用多了点,但是速度快才是王道。

         2.2 PrepareStatement可滚动ResultSet配置:

              (1) java.sql.Connection.PreparedStatement prepareStatement(String sql,int resultSetType,int resultSetConcurrency);

              (2) java.sql.Connection.PreparedStatement prepareStatement(String sql,int resultSetType,int resultSetConcurrency,int resultSetHoldability);

              参数及其用法详见上面1.3。

      3. CallableStatement接口常用的2个方法:

             (1) executeUpdate(String sql) :执行insert / update / delete 等SQL语句,成功返回影响数据库记录行数的int整数型。

             (2) executeQuery(String sql) : 执行查询语句,成功返回一个ResultSet类型的结果集对象。

[java] view plain copy
 java数据库连接(一)--从最简单地jdbc连接说起java数据库连接(一)--从最简单地jdbc连接说起
  1. ResultSet rs = null;  
  2. CallableStatement cs;  
  3. try {  
  4.     cs = conn.prepareCall("{call p_insert(?,?)}");  
  5.     cs.setString(1"No1.");  
  6.     cs.setString(2"****");  
  7.     int num = cs.executeUpdate();  
  8. catch (SQLException e) {  
  9.     // TODO Auto-generated catch block  
  10.     e.printStackTrace();  
  11.         conn.rollback();  
  12. }finally{  
  13.     JdbcUtil.close(rs, stmt, conn);  
  14. }  
  15.   
  16. try {  
  17.     cs = conn.prepareCall("{call p_select(?)}");  
  18.     cs.setString(1,  "No1.");  
  19.     rs = cs.executeQuery();  
  20. catch (SQLException e) {  
  21.     // TODO Auto-generated catch block  
  22.     e.printStackTrace();  
  23.         conn.rollback();  
  24. }finally{  
  25.     JdbcUtil.close(rs, stmt, conn);  
  26. }