zoukankan      html  css  js  c++  java
  • javaweb三、JDBC访问数据库

    JDBC是J2SE的内容,是由java提供的访问数据库的接口,但没有提供具体的实现方法,需要数据库厂商提供,就是对应的数据库驱动。

    这样的好处是可以方便的更换数据库,提高了扩展性。这也是面向接口编程的一个优点。

      1 import java.sql.Connection;
      2 import java.sql.DriverManager;
      3 import java.sql.ResultSet;
      4 import java.sql.SQLException;
      5 import java.sql.Statement;
      6 
      7 public class Demo {
      8     public static void main(String[] args) throws ClassNotFoundException, SQLException{
      9         //连接数据库,获取连接对象
     10         Connection conn=connection();
     11         //使用连接对象进行数据库的操作:增、删、改
     12         sqlDemo(conn);
     13         //使用连接对象进行数据库的操作:查
     14         queryDemo(conn);
     15                 //sql规范写法,
     16                 sqlDemo2();
     17     }
     18 
     19     public static Connection connection() throws ClassNotFoundException, SQLException {
     20         
     21         /*注册数据库驱动对象的简便方法:
     22          * Java中在使用数据库对象时,需要通过相应的驱动来实现,并且要通过DriverManager类来注册这个驱动
     23          * 上面的操作已经被写入驱动类中的静态代码块中了,所以可以直接加载该类就实现了上述操作
     24          * 
     25          * 在jdbc4.0之后的版本中有些数据库驱动有一个配置文件可以进行注册,也就是可以省略下面一句,
     26          * 但是并非所有驱动都可以,而且为了兼容性更好,建议使用
     27          */
     28         Class.forName("com.mysql.jdbc.Driver");
     29         
     30         //获取数据库连接对象
     31         /*jdbc四大配置参数
     32          * driverClassName(与使用的数据库对应):com.mysql.jdbc.Driver
     33          * url:(Java连接数据库的地址,非http协议的url)jdbc:mysql://localhost:3306/库名
     34          * user:数据库用户名
     35          * password:数据库密码
     36          */
     37         String url="jdbc:mysql://localhost:3306/test";
     38         String user="root";
     39         String password="920346";
     40         Connection _conn=DriverManager.getConnection(url, user, password);
     41         return _conn;
     42     }
     43     
     44     public static void sqlDemo(Connection conn) throws SQLException {
     45         /*发送sql语句需要使用Statement对象,语句是正常的sql语句,注意不要加;结束
     46          * 增删改语句的发送使用executeUpdate();返回受影响行数
     47          */
     48         Statement stat=conn.createStatement();
     49         String sql="INSERT INTO test1 VALUES(2,3)";
     50         int l=stat.executeUpdate(sql);
     51         sql="UPDATE test1 SET num1=2 WHERE num1=1";
     52         l=stat.executeUpdate(sql);
     53         sql="DELETE FROM test1 WHERE num1=2";
     54         l=stat.executeUpdate(sql);
     55         System.out.println(l);
     56     }
     57 
     58     private static void queryDemo(Connection conn) throws SQLException {
     59         /*查询语句和上面的增删改的不同在于返回值:
     60          * 1、查询返回结果集;其他返回影响行数
     61          * 2、查询使用的是executeQuery();其他使用executeUpdate()
     62          */
     63         /*在创建语句发送器对象时,就已经决定了获取的结果集对象的特性,可以通过参数进行设置
     64          * 默认只能向下移动,即执行next()
     65          */
     66         Statement stat=conn.createStatement();
     67         String sql="SELECT * FROM test1";
     68         /*查询得到的结果集对象就是对数据表的抽象,是一张表,有行有列,对结果集的操作就是对行和列的操作
     69          * 对行的操作就是定位、移动和获取行数                --》结果集光标
     70          * 对列的操作就是获取列的信息(列数/类型),获取列的值    --》元数据
     71          */
     72         ResultSet rs=stat.executeQuery(sql);
     73         while(rs.next()){
     74             int num1=rs.getInt("num1");
     75             int num2=rs.getInt(2);
     76             System.out.println("num1="+num1+",num2="+num2);
     77         }
     78         
     79         //数据库连接也是一种资源,使用之后必须关闭,而且上面的三个对象都要关闭
     80         rs.close();
     81         stat.close();
     82         conn.close();
     83     }
     84 
     85     //sql代码书写规范:包括异常处理
     86     public static void sqlDemo2(){
     87         Connection conn=null;
     88         Statement stat=null;
     89         try{
     90             conn=connection();
     91             stat=conn.createStatement();
     92             String sql="INSERT INTO test1 VALUES(2,3)";
     93             int l=stat.executeUpdate(sql);
     94             sql="UPDATE test1 SET num1=2 WHERE num1=1";
     95             l=stat.executeUpdate(sql);
     96             sql="DELETE FROM test1 WHERE num1=2";
     97             l=stat.executeUpdate(sql);
     98             System.out.println(l);
     99         }catch(Exception e){
    100             throw new RuntimeException();
    101         }finally{
    102             //防止空指针异常
    103             try{
    104                 if(stat!=null)
    105                     stat.close();
    106                 if(conn!=null)
    107                     conn.close();
    108             }catch(SQLException e){
    109                 throw new RuntimeException();
    110             }
    111         }
    112     }
    113 }                                                        
    JDBC第一例

    上面的查询使用的是Statement对象,但是有一个缺点就是可能存在Sql攻击德尔问题,可以使用PreapredStatement对象最为替代,

      1 import java.io.IOException;
      2 import java.sql.Connection;
      3 import java.sql.DriverManager;
      4 import java.sql.PreparedStatement;
      5 import java.sql.ResultSet;
      6 import java.sql.SQLException;
      7 import java.sql.Statement;
      8 
      9 import org.junit.Test;
     10 
     11 
     12 /**
     13  * PreapredStatement的使用:
     14  * 防SQL攻击
     15  * @author cxf
     16  *
     17  */
     18 public class Demo2 {
     19     /**
     20      * 登录
     21      * 使用username和password去查询数据
     22      * 若查出结果集,说明正确!返回true
     23      * 若查出不出结果,说明用户名或密码错误,返回false
     24      * @param username
     25      * @param password
     26      * @return
     27      * @throws Exception 
     28      */
     29     public boolean login(String username, String password) throws Exception {
     30         /*
     31          * 一、得到Connection
     32          * 二、得到Statement
     33          * 三、得到ResultSet
     34          * 四、rs.next()返回的是什么,我们就返回什么
     35          */
     36         // 准备四大参数
     37         String driverClassName = "com.mysql.jdbc.Driver";
     38         String url = "jdbc:mysql://localhost:3306/test";
     39         String mysqlUsername = "root";
     40         String mysqlPassword = "920346";
     41         // 加载驱动类
     42         Class.forName(driverClassName);
     43         // 得到Connection
     44         Connection con = DriverManager.getConnection(url, mysqlUsername, mysqlPassword);
     45         
     46         // 得到Statement
     47         Statement stmt = con.createStatement();
     48         
     49         // 给出sql语句,调用stmt的executeQuery(),得到ResultSet
     50         String sql = "select * from j_stu where username='" + username + "' and password='" + password + "'";
     51         System.out.println(sql);
     52         ResultSet rs = stmt.executeQuery(sql);
     53         
     54         return rs.next();
     55     }
     56     
     57     /**
     58      * SQL攻击!
     59      * @throws Exception
     60      */
     61     @Test
     62     public void fun1() throws Exception {
     63         //select * from t_user where username='a' or 'a'='a' and password='a' or 'a'='a'
     64         String username = "a' or 'a'='a";
     65         String password = "a' or 'a'='a";
     66         boolean bool = login(username, password);
     67         System.out.println(bool);
     68     }
     69     
     70     public boolean login2(String username, String password) throws Exception {
     71         /*
     72          * 一、得到Connection
     73          * 二、得到Statement
     74          * 三、得到ResultSet
     75          * 四、rs.next()返回的是什么,我们就返回什么
     76          */
     77         // 准备四大参数
     78         String driverClassName = "com.mysql.jdbc.Driver";
     79         String url = "jdbc:mysql://localhost:3306/test?useServerPrepStmts=true&cachePrepStmts=true";
     80         String mysqlUsername = "root";
     81         String mysqlPassword = "920346";
     82         // 加载驱动类
     83         Class.forName(driverClassName);
     84         // 得到Connection
     85         Connection con = DriverManager.getConnection(url, mysqlUsername, mysqlPassword);
     86         
     87         ///////////////////////////////////////
     88         ///////////////////////////////////////
     89         
     90         
     91         /*
     92          * 一、得到PreparedStatement
     93          * 1. 给出sql模板:所有的参数使用?来替代
     94          * 2. 调用Connection方法,得到PreparedStatement
     95          */
     96         String sql = "select * from j_stu where username=? and password=?";
     97         PreparedStatement pstmt = con.prepareStatement(sql);
     98         
     99         /*
    100          * 二、为参数赋值
    101          */
    102         pstmt.setString(1, username);//给第1个问号赋值,值为username
    103         pstmt.setString(2, password);//给第2个问号赋值,值为password
    104         
    105         ResultSet rs = pstmt.executeQuery();//调用查询方法,向数据库发送查询语句
    106         
    107         //重复使用赋值,需要关闭上次的结果流,并清空原设置
    108         rs.close();
    109         pstmt.clearParameters();
    110         
    111         pstmt.setString(1, "liSi");
    112         pstmt.setString(2, "123");
    113         rs = pstmt.executeQuery();//调用查询方法,向数据库发送查询语句
    114         
    115         return rs.next();
    116     }
    117     
    118     @Test
    119     public void fun2() throws Exception {
    120         //select * from t_user where username='a' or 'a'='a' and password='a' or 'a'='a'
    121         String username = "zhangSan";
    122         String password = "123";
    123         boolean bool = login2(username, password);
    124         System.out.println(bool);
    125     }
    126     
    127     /**
    128      * 测试JdbcUtils.getConnection()
    129      * @throws SQLException 
    130      * @throws ClassNotFoundException 
    131      * @throws IOException 
    132      */
    133     @Test
    134     public void fun3() throws SQLException {
    135         Connection con = JdbcUtils.getConnection();
    136         System.out.println(con);
    137         Connection con1 = JdbcUtils.getConnection();
    138         System.out.println(con1);
    139     }
    140 }
    使用PreapredStatement防止sql攻击
     1 import java.sql.Connection;
     2 import java.sql.SQLException;
     3 
     4 import org.junit.Test;
     5 
     6 public class Demo5 {
     7     /*jdbc中使用事务的演示:转账
     8      * !!!事务是由连接对象管理,所以事务过程必须使用同一个连接对象
     9      */
    10     public void transfers(String from,String to,Double money){
    11         Connection conn=null;
    12         try{
    13             conn=JdbcUtils.getConnection();
    14             //开启事务
    15             conn.setAutoCommit(false);
    16             //执行事务内容
    17             AccountDao dao=new AccountDao();
    18             dao.updateBalance(conn,from, -money);
    19             dao.updateBalance(conn,to, money);
    20             //提交事务
    21             conn.commit();
    22             conn.close();
    23         }catch(Exception e){
    24             try {
    25                 conn.rollback();
    26                 conn.close();
    27             } catch (SQLException e1) {
    28                 throw new RuntimeException(e);
    29             }
    30         }
    31     }
    32     @Test
    33     public void fun1(){
    34         transfers("zs","lisi",100.00);
    35     }
    36 }
    事务管理

    从上面的基础代码可以看出有三个对象非常重要:Connection,Statement/PreparedStatement,ResultSet.还有就是注册驱动有多种方式,上面使用的是推荐用法。

    以上就是JDBC的基本使用,但是也存在一些问题,

    ①数据库连接使用完之后需要释放,如果经常需要连接影响性能。

    ②数据库的使用代码有很多都是重复的,例如获取Connection对象,异常处理等。

    ③对查询结果集Result对象的处理

    针对上面问题的解决方案:

    ①使用连接池代替原始的数据库连接,连接池就是一种装饰者模式,对连接对象的close()进行增强。

     1 import java.beans.PropertyVetoException;
     2 import java.sql.Connection;
     3 import java.sql.SQLException;
     4 
     5 import org.apache.commons.dbcp.BasicDataSource;
     6 import org.junit.Test;
     7 
     8 import com.mchange.v2.c3p0.ComboPooledDataSource;
     9 
    10 public class Demo6 {
    11     /*使用数据库连接池获取连接对象,连接池的配置还可以在配置文件中作为资源进行配置,称为JNDI,
    12      * 1、DBCP连接池
    13      * 2、C3P0连接池
    14      */
    15     @Test
    16     public void fun1() throws SQLException{
    17         //数据库连接池是装饰者模式,是对Connection对象进行增强,
    18         //获取连接池对象
    19         BasicDataSource dataSource=new BasicDataSource();
    20         //配置连接参数,因为连接池也要依靠四大参数连接数据库,并且也需要使用数据库驱动
    21         dataSource.setDriverClassName("com.mysql.jdbc.Driver");
    22         dataSource.setUrl("jdbc:mysql://localhost:3306/test");
    23         dataSource.setUsername("root");
    24         dataSource.setPassword("920346");
    25         //配置池参数:有默认值,
    26         dataSource.setMaxActive(20);    //最大活动连接数
    27         dataSource.setMaxIdle(3);        //最大空闲连接数
    28         
    29         //获取连接对象
    30         Connection conn=dataSource.getConnection();
    31         System.out.println(conn.getClass().getName());
    32         
    33         //注意这里的close()被增强,不是关闭连接,而是将连接对象归还连接池
    34         conn.close();
    35     }
    36     
    37     @Test
    38     public void fun2() throws SQLException, PropertyVetoException{
    39         //获取连接池对象,和上面操作相似,只是名字有所不同
    40         ComboPooledDataSource dataSource=new ComboPooledDataSource();
    41         
    42         //注意方法名和上面不同
    43         dataSource.setDriverClass("com.mysql.jdbc.Driver");
    44         dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
    45         dataSource.setUser("root");
    46         dataSource.setPassword("920346");
    47         
    48         //配置池参数:有默认值,
    49         dataSource.setAcquireIncrement(5);
    50         dataSource.setInitialPoolSize(20);
    51         
    52         //获取连接对象
    53         Connection conn=dataSource.getConnection();
    54         System.out.println(conn.getClass().getName());
    55         
    56         //注意这里的close()被增强,不是关闭连接,而是将连接对象归还连接池
    57         conn.close();
    58     }
    59     @Test
    60     public void fun3() throws SQLException{
    61         /*c3p0连接池的配置参数可以直接写在配置文件中,
    62          * 只要将配置文件保存在类路径下即可在创建类时自动寻找
    63          * 注意:默认情况下使用的是默认配置,如果在代码中在进行配置就会将配置文件中的覆盖
    64          */
    65         ComboPooledDataSource dataSource=new ComboPooledDataSource();
    66         
    67         Connection conn=dataSource.getConnection();
    68         System.out.println(conn.getClass().getName());
    69         
    70         conn.close();
    71     }
    72     public void fun4() throws SQLException{
    73         //在配置文件中可以有多个配置,如果不使用默认配置二使用其他配置,只要将节点名作为参数传入即可
    74         ComboPooledDataSource dataSource=new ComboPooledDataSource("oracle-config");
    75         
    76         Connection conn=dataSource.getConnection();
    77         System.out.println(conn.getClass().getName());
    78         
    79         conn.close();
    80     }
    81 }
    数据库连接池的使用

    ②使用Apache Commons dbUtils包进行处理

    ③使用Apache Commons dbUtils包将结果集与java中的对象,集合等结构进行操作

    对Apache Commons dbUtils包的说明参见

    http://www.jb51.net/article/61886.htm

    http://lavasoft.blog.51cto.com/62575/222771/

    http://www.cnblogs.com/xdp-gacl/p/4007225.html

  • 相关阅读:
    基于jQuery的一个弹出层
    获取一个数组内的最大最小值
    flex内根据id(string)获取对象
    整理的一份iframe编辑器代码
    仿163邮箱工具条
    获取dom到浏览器窗口坐上坐标
    the solution to fix 'Failed to access IIS metabase'
    .Net下的Windows服务程序开发指南.
    Castle学习笔记之Windsor(二)
    IOC:主要概念
  • 原文地址:https://www.cnblogs.com/songfeilong2325/p/4808526.html
Copyright © 2011-2022 走看看