20.java-JDBC连接mysql数据库详解

1.JDBC介绍

jdbc(java database connectivity)为java开发者使用数据库提供了统一的编程接口,它由一组java类和接口组成。

JDBC需要用到的类和接口有:

DriverManager、Connection、Statement、ResultSet         

 

2. mysql-connector-java下载

本机的mysql版本是5.7.26 win32的,所以本章访问mysql都以该版本为例:

 

然后进入https://dev.mysql.com/downloads/connector/j/下载mysql-connector-java.jar包,用于连接mysql

如下图所示,只有8.0.19版本,那我们下载它就好了,反正不管64位还是32位都能访问:

 

下载解压后,就有个mysql-connector-java-8.0.19.jar:

 

接下来就来测试,能不能访问

 

3.JDBC使用过程

3.1 通过DriverManager. registerDriver(Driver driver)来注册驱动程序

需要注意,new Driver的时候,需要选择com.mysql.cj.jdbc.Driver:

 

因为com.mysql.jdbc.Driver已经被弃用了.

PS:也可以直接将DriverManager. registerDriver(Driver driver)改为:

Class.forName("com.mysql.cj.jdbc.Driver");
//加载一下这个类就可以注册驱动,因为mysql Driver类的静态代码块中已经调用了registerDriver()来注册驱动程序.

 

3.2 然后通过 Connection DriverManager.getConnection(String url, String user, String password)来连接数据库,并获取Connection对象

url: 填入“jdbc:子协议://ip地址:端口号/数据库名” ,如果是mysql则填入“jdbc:mysql://localhost:3306/数据库名”

针对mysql-connector-java-8.0以上的版本,则还要追加"?characterEcoding=utf-8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true"

username:mysql用户名

password:mysql密码

 

3.3 通过Connection对象获取statement对象

Statement statement = connection.createStatement();

 

3.4 通过statement对象的executeQuery(String)来执行查询sql语句,并返回ResultSet数据库结果集

比如:

ResultSet  resultSet = statement. executeQuery("select * from student");       //获取student表里的数据

除此之外还有int executeUpdate(String sql)方法.用来实现INSERT、UPDATE 或 DELETE 语句,返回值表示执行sql语句之后影响到的数据行数 (后面示例有讲)

 

3.5 然后通过ResultSet来读出query内容

ResultSet常用方法如下:

boolean first();             //移到内容第一行数据处

boolean  last();             //移到内容最后一行数据处

int getRow() ;             //获取当前光标处于的行号

boolean isLast()           //获取光标是否位于此 ResultSet 对象的最后一行。

boolean   next();          //移到下一行数据处,然后就可以通过getXXX()获取完当前一行数据后,则通过next()来移动到下行继续getXXX(),直到next()返回为false为止

boolean   previous();     //移到上一行数据处

String getString(String columnLabel);  //获取当前一行的columnLabel列名的内容                             

String  getString(int columnIndex);   //获取当前一行的第columnIndex列的内容,第一列是从1开始的.

         String getInt (String columnLabel);  //获取当前一行的columnLabel列名的内容                     

String  getInt(int columnIndex);  //获取当前一行的第columnIndex列的内容,第一列是从1开始的.

 
//...除此之外,还有getFloat(),getLong(),getShort(),getURL(),getBoolean(),getRowId()

 PS:获取到ResultSet后,必须先next()一次才能getXXX(),来获取内容

 

3.6 访问结束后,释放Mysql资源(毕竟mysql连入个数是有限的) 

    try {
            if(resultSet!=null){
            resultSet.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } 
        try {
            if(statement!=null){
            statement.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        try {
            if(connection!=null){
            connection.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

 

4.本章要访问的数据库以students为例:

 

 

5.首先来写JdbcUtils工具类

JdbcUtils工具类里主要写getConnection(),releaseResc()这两个类,这样避免后续的重复代码产生.

JdbcUtils.java代码如下所示:

public class JdbcUtils {

    private static String driver;
    private static String url;
    private static String user;
    private static String pwd;

    static{
        
        driver = "com.mysql.cj.jdbc.Driver";
        url = "jdbc:mysql://localhost:3306/students?characterEcoding=utf-8&"    
                + "useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true";
    
        user = "root";
        pwd = "sql";
        
    }
    
    
    //获取一个链接mysql的Connection对象
    static public Connection getConnection(){
        
        try {
            Class.forName(driver);
             Connection connection = DriverManager.getConnection(url,user,pwd);
             return connection;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        
    }
    
    /**
     * 释放Mysql资源(毕竟mysql连入个数是有限的)    
     * @param resultSet 结果集
     * @param statement 
     * @param connection 链接
     */
    public static void releaseResc(ResultSet resultSet, Statement statement, Connection connection) {
    
        try {
            if(resultSet!=null){
            resultSet.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } 
        try {
            if(statement!=null){
            statement.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        try {
            if(connection!=null){
            connection.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

 

6.数据库查询示例

查询所有学生的信息:

@Test
    public void jdbcQuery(){
        
        ResultSet resultSet = null;
        Statement statement = null;
        Connection connection = null;
        try {
            connection = JdbcUtils.getConnection();        //通过JdbcUtils获取connection
            statement = connection.createStatement();
            
            String sql = "select * from student";
            
            resultSet = statement.executeQuery(sql);
        
            while(resultSet.next()){
                
                String name = resultSet.getString("name");
                String score = resultSet.getString("score");
                String classs = resultSet.getString("class");
                
                System.out.println("姓名:"+name+"  成绩:"+score+"  班级:"+classs);
            }
            
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            
            JdbcUtils.releaseResc(resultSet, statement, connection);        //释放资源
        }
    }

打印如下所示:

 

 

7.数据库插入示例

@Test
    public void jdbcInser(){
        
        ResultSet resultSet = null;
        Statement statement = null;
        Connection connection = null;
         
        try {
            connection = JdbcUtils.getConnection();
            statement = connection.createStatement();
            
            String name = "小f";
            int score = 99;
            String classs = "初2-4班";
            
            String sql = "INSERT INTO  student(name,score,class) "        
                       +" values('"+name+"','"+String.valueOf(score)+"','"+classs+"')";
            
            int result = statement.executeUpdate(sql); 
            //executeUpdate:用来实现INSERT、UPDATE 或 DELETE 语句,返回值表示执行sql语句之后影响到的数据行数 
            
            System.out.println("插入了"+result+"条数据");
            
            
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            
            JdbcUtils.releaseResc(resultSet, statement, connection);        //释放资源
        }
    }

运行打印:

 

查看数据库:

 

8.数据库更新示例

将所有低于60分的同学的成绩改为0:

@Test
    public void jdbcUpdate(){
        
        ResultSet resultSet = null;
        Statement statement = null;
        Connection connection = null;
        
        try {
            connection = JdbcUtils.getConnection();
             statement = connection.createStatement();
            
        
            String sql = "update student  SET score='0'  WHERE  score<60";
            
            
            int result = statement.executeUpdate(sql); 
            //executeUpdate:用来实现INSERT、UPDATE 或 DELETE 语句,返回值表示执行sql语句之后影响到的数据行数 
            
            System.out.println("更新了"+result+"条数据");
            
            
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            
            JdbcUtils.releaseResc(resultSet, statement, connection);        //释放资源
        }
        
    }

查看数据库:

 

 

9.SQL 注入攻击

Statement采取直接编译 SQL 语句的方式,扔给数据库去执行,所以很容易进行被SQL注入攻击.

比如:

我们登陆执行时需要执行:

statement.executeQuery("select id from users where name ='"+username+"' and password = '"+password+"'");

而黑客则将字符串直接改为:

statement.executeQuery("select id from users where name ='"+username+"' or '1==1' and password = '"+password+"'");

就可以直接乱输入密码也能实现登录了,所以java中提供了另一个类PreparedStatement, 采用"?"占位符预编译,再填充参数,用来避免SQL注入攻击.

 

PreparedStatement类介绍

采用"?"占位符预编译,再填充参数,然后通过setXXX()来填充参数.比如setString():

setString(int parameterIndex, String x);       //向第parameterIndex个占位符填入x内容
// parameterIndex:第一个?占位符是1,第二个是2....

//...除了该方法之外,还有setFloat(),setLong(),setBoolean()....等等

 

修改登录界面之PreparedStatement使用如下所示:

public static boolean login(String username,String password){
          Connection connection = JdbcUtils.getConnection();                  //获取
                  try {

                          String sql = "select id from users where username =? and password = ?"; //要运行的sql语句,通过?来替换登录账号和密码

                          PreparedStatement preparedStatement = connection.prepareStatement(sql);

                          //第一个? 用username字符串去替换
                          preparedStatement.setString(1, username);

                          //第二个? 用password字符串去替换
                          preparedStatement.setString(2, password);

                          ResultSet resultSet = preparedStatement.executeQuery();

                          return resultSet.next();            //有值则返回true,否则返回false;

                  } catch (SQLException e) {
                          e.printStackTrace();
                          return false;
                  }
 }

 

 

 

 

 

 

posted @ 2020-01-14 17:09  诺谦  阅读(8528)  评论(0编辑  收藏  举报