JDBC------数据库,事务,连接池

1.数据库驱动

驱动:声卡,显卡、数据库
在这里插入图片描述程序通过数据库驱动和数据库联系

2.JDBC

SUN 公司为了简化 开发人员的(对数据库的统一)操作,提供了一个(Java操作数据库的)规范,俗称 JDBC
这些规范的实现由具体的厂商去做~
对于开发人员来说,我们只需要掌握 JDBC 接口的操作即可!

在这里插入图片描述
java.sql
javax.sql
还需要导入一个数据库驱动包 mysql-connector-java-5.1.47.jar

3.第一个JDBC程序

创建测试数据库

CREATE DATABASE jdbcStudy CHARACTER SET utf8 COLLATE utf8_general_ci;
USE jdbcStudy;
CREATE TABLE users(    
    id INT PRIMARY KEY,    
    NAME VARCHAR(40),    
    PASSWORD VARCHAR(40),    
    email VARCHAR(60),    
    birthday DATE 
);
INSERT INTO users(id,NAME,PASSWORD,email,birthday) VALUES(1,'zhansan','123456','[email protected]','1980-12-04'), (2,'lisi','123456','[email protected]','1981-12-04'), (3,'wangwu','123456','[email protected]','1979-12-04');

创建JDBC流程

1、加载驱动
2、连接数据库 DriverManager 右键drive as library
3、获得执行sql的对象 Statement
4、获得返回的结果集
5、释放连接

import java.sql.*;
// 我的第一个JDBC程序 
public class JdbcFirstDemo {    
public static void main(String[] args) throws ClassNotFoundException, SQLException {        
//1. 加载驱动        
Class.forName("com.mysql.jdbc.Driver"); 
// 固定写法,加载驱动
        
//2. 用户信息和url        
// useUnicode=true&characterEncoding=utf8&useSSL=true        
String url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true";        
String username = "root";
String password = "123456";        
//3. 连接成功,数据库对象  Connection 代表数据库        
Connection connection = DriverManager.getConnection(url, username, password);
        
//4. 执行SQL的对象 Statement 执行sql的对象        
Statement statement = connection.createStatement();
//5. 执行SQL的对象 去 执行SQL,可能存在结果,查看返回结果        
String sql = "SELECT * FROM users";
ResultSet resultSet = statement.executeQuery(sql);
//返回的结果集,结果 集中封装了我们全部的查询出来的结果
       
while (resultSet.next()){           
System.out.println("id=" + resultSet.getObject("id"));            System.out.println("name=" + resultSet.getObject("NAME"));            System.out.println("pwd=" + resultSet.getObject("PASSWORD"));            System.out.println("email=" + resultSet.getObject("email"));            System.out.println("birth=" + resultSet.getObject("birthday"));            System.out.println("==================================");        
}
//6、释放连接        
resultSet.close();        
statement.close();        
connection.close();
    } 
}

DriverManger

// DriverManager.registerDriver(new com.mysql.jdbc.Driver()); Class.forName("com.mysql.jdbc.Driver"); // 固定写法,加载驱动 Connection connection = DriverManager.getConnection(url, username, password);
// connection 代表数据库 
// 数据库设置自动提交 
// 事务提交 
// 事务滚回 
connection.rollback(); 
connection.commit(); 
connection.setAutoCommit();

URL

String url = "jdbc:mysql://localhost:3306/jdbcstudy? useUnicode=true&characterEncoding=utf8&useSSL=true";
// mysql -- 3306 // 协议 ://主机地址:端口号/数据库名?参数1&参数2&参数3
// oralce -- 1521 
//jdbc:oracle:thin:@localhost:1521:sid

Statement执行SQL的对象 PrepareStatement执行SQL的对象

String sql = "SELECT * FROM users"; // 编写SQL
statement.executeQuery(); //查询操作返回 ResultSet 
statement.execute(); // 执行任何SQL 
statement.executeUpdate();  // 更新、插入、删除。都是用这个,返回一个受影响的行数

ResultSet 查询的结果集:封装了所有的查询结果

获得指定的数据类型

resultSet.getObject(); // 在不知道列类型的情况下使用 
// 如果知道列的类型就使用指定的类型 
resultSet.getString(); 
resultSet.getInt(); 
resultSet.getFloat(); 
resultSet.getDate(); 
resultSet.getObject(); 
....

遍历,指针

resultSet.beforeFirst();  // 移动到前面 
resultSet.afterLast();   // 移动到后面 
resultSet.next(); //移动到下一个数据 
resultSet.previous(); //移动到前一行 
resultSet.absolute(row); //移动到指定行

释放资源

//6、释放连接 
resultSet.close(); 
statement.close(); 
connection.close(); // 耗资源,用完关掉!

4 statement对象

Jdbc中的statement对象用于向数据库发送SQL语句,想完成对数据库的增删改查,只需要通过这个对象 向数据库发送增删改查语句即可

  • Statement对象的executeUpdate方法,用于向数据库发送增、删、改的sql语句,executeUpdate执行 完后,将会返回一个整数(即增删改语句导致了数据库几行数据发生了变化)。
  • Statement.executeQuery方法用于向数据库发送查询语句,executeQuery方法返回代表查询结果的 ResultSet对象

CRUD操作-create

Statement st = conn.createStatement(); String sql = "insert into user(….) values(…..) "; int num = st.executeUpdate(sql); if(num>0){    System.out.println("插入成功!!!"); }

CRUD操作-delete

Statement st = conn.createStatement(); 
String sql = "delete from user where id=1"; 
int num = st.executeUpdate(sql); 
if(num>0){    
System.out.println(“删除成功!!!"); 
}

CRUD操作-update

Statement st = conn.createStatement(); 
String sql = "update user set name='' where name=''"; 
int num = st.executeUpdate(sql); 
if(num>0){    
System.out.println(“修改成功!!!"); 
}

CRUD操作-read

Statement st = conn.createStatement(); 
String sql = "select * from user where id=1"; 
ResultSet rs = st.executeQuery(sql); 
while(rs.next()){    
//根据获取列的数据类型,分别调用rs的相应方法映射到java对象中 
}

代码实现

在src下建立资源文件 db.properties

driver=com.mysql.jdbc.Driver 
url=jdbc:mysql://localhost:3306/jdbcstudyuseUnicode=true&characterEncoding=utf8&useSSL=true 
username=root 
password=123456

1.提取工具类

import java.io.IOException; 
import java.io.InputStream; 
import java.sql.*; 
import java.util.Properties;
public class JdbcUtils {
    private static String driver = null;    
    private static String url = null;    
    private static String username = null;    
    private static String password = null;
    static {        
    try{            
    InputStream in =  JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");                   
    Properties properties = new Properties();            
    properties.load(in);
            
    driver = properties.getProperty("driver");            
    url = properties.getProperty("url");            
    username = properties.getProperty("username");            
    password = properties.getProperty("password");
            
    //1.驱动只用加载一次            
    Class.forName(driver);        
    } catch (Exception e) {           
     e.printStackTrace();        
     }
 }
    //获取连接    
    public static Connection getConnection() throws SQLException {        
    return DriverManager.getConnection(url, username, password);    }
    //释放连接资源    
    public static void release(Connection conn, Statement st, ResultSet rs){        
    if (rs!=null){            
      try {                
        rs.close();            
      } catch (SQLException e) {                
        e.printStackTrace();            
    }        
}        
     if (st!=null){         
        try {           
             st.close();         
        } catch (SQLException e) {
             e.printStackTrace();        
        }       
      }       
      if (conn!=null){        
         try {             
           conn.close();            
         } catch (SQLException e) {                
           e.printStackTrace();        
         }       
         }
          
       }
}

编写增删改的方法,executeUpdate

import com.kuang.lesson02.utils.JdbcUtils;
import java.sql.Connection; 
import java.sql.ResultSet; 
import java.sql.SQLException; 
import java.sql.Statement;
public class TestInsert {
    public static void main(String[] args) {
        Connection conn = null;
        Statement st = null;        
        ResultSet rs = null;
        try {
                conn = JdbcUtils.getConnection(); //获取数据库连接                   
                st = conn.createStatement(); //获得SQL的执行对象
                
                String sql = "INSERT INTO users(id,`NAME`,`PASSWORD`,`email`,`birthday`)" +                    "VALUES(4,'kuangshen','123456','[email protected]','202001-01')";
                
                int i = st.executeUpdate(sql);            
                if (i>0){                
                System.out.println("插入成功!");            
                }
        } catch (SQLException e) {           
         e.printStackTrace();        
         } finally {            
         JdbcUtils.release(conn,st,rs);       
          }
    } 
    }

查询 executeQuery

import com.kuang.lesson02.utils.JdbcUtils;
import java.sql.Connection; 
import java.sql.ResultSet; 
import java.sql.SQLException; 
import java.sql.Statement;
public class TestSelect {
    public static void main(String[] args) {   
         Connection conn =null;        
         Statement st = null;        
         ResultSet rs = null;        
         try {      
               conn = JdbcUtils.getConnection();      
               st = conn.createStatement();
               //SQL           

               String sql = "select * from users where id = 1";
               rs = st.executeQuery(sql); //查询完毕会返回一个结果集            
               while (rs.next()){                
                  System.out.println(rs.getString("NAME"));            
                  }                    
               } catch (SQLException e) {
                  e.printStackTrace();        
               } finally {                                                 JdbcUtils.release(conn,st,rs);      
                 }
    } 
    }

SQL注入的问题
sql 存在漏洞,会被攻击导致数据泄露,SQL会被拼接 or

import com.kuang.lesson02.utils.JdbcUtils;
import java.sql.Connection; 
import java.sql.ResultSet; 
import java.sql.SQLException; 
import java.sql.Statement;
public class SQL注入 {
    public static void main(String[] args) {
         login(" 'or '1=1"," 'or'1=1"); // 技巧
    }
    // 登录业务    
    public static void login(String username,String password){
        Connection conn =null;        
        Statement st = null;        
        ResultSet rs = null;        
        try {        
            conn = JdbcUtils.getConnection();            
            st = conn.createStatement();
            // SELECT * FROM users WHERE `Name` = 'kuangshen' AND `password` = '123456';
            // SELECT * FROM users WHERE `Name` = '' or '1=1' AND `password` = '' or '1=1';            
            String sql = "select * from users where `NAME`='"+username+"' AND `password` ='"+password+"'";
            rs = st.executeQuery(sql); //查询完毕会返回一个结果集                     
            while (rs.next()){                
            System.out.println(rs.getString("NAME"));                
            System.out.println(rs.getString("password"));                
            System.out.println("============================");            
            }
        } catch (SQLException e) {        
            e.printStackTrace();        
        } finally {            
            JdbcUtils.release(conn,st,rs);        
        }
    }
}

1.新增

import bao1.JdbcUtils;

import java.sql.Connection;
import java.util.Date;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class TestInsert {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement st = null;

        try{
            conn = JdbcUtils.getConnection();

            String sql = "insert into users(`id`,`NAME`,`PASSWORD`,`email`,`birthday`) values(?,?,?,?,?)";

            st = conn.prepareStatement(sql);

            st.setInt(1,5);
            st.setString(2,"yang");
            st.setString(3,"12322213");
            st.setString(4,"[email protected]");

            st.setDate(5,new java.sql.Date(new Date().getTime()));

            int i = st.executeUpdate();
            if(i>0){
                System.out.println("插入成功!");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            JdbcUtils.release(conn,st,null);
        }
    }
}

2.删除

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class TestDelete {
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement st = null;

        try{
            conn = JdbcUtils.getConnection();

            String sql = "delete from users where id=?;";

            st = conn.prepareStatement(sql);

            st.setInt(1,4);

            int i = st.executeUpdate();
            if(i>0) {
                System.out.println("删除成功!");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            JdbcUtils.release(conn,st,null);
        }
    }
}

3、更新

import java.sql.Connection; 
import java.sql.PreparedStatement; 
import java.sql.SQLException;
public class TestUpdate {
    public static void main(String[] args) {
            Connection conn = null;        
            PreparedStatement st = null;
        
        try {
             conn = JdbcUtils.getConnection();            
                    // 区别            
                    // 使用? 占位符代替参数            
             String sql = "update users set `NAME`=?  where id=?;";
            
            st = conn.prepareStatement(sql); //预编译SQL,先写sql,然后不执行
            // 手动给参数赋值           
            st.setString(1,"狂神");           
            st.setInt(2,1);
            //执行            
            int i = st.executeUpdate();            
            if (i>0){         
                   System.out.println("更新成功!");            
                   }
        } catch (SQLException e) {          
          e.printStackTrace();       
           } finally {            
           JdbcUtils.release(conn,st,null);       
            }
    } 
    }

4、查询

import java.sql.Connection; 
import java.sql.PreparedStatement; 
import java.sql.ResultSet; 
import java.sql.SQLException;
public class TestSelect {
    public static void main(String[] args) {
        Connection conn = null;        
        PreparedStatement st = null;       
        ResultSet rs = null;
        try {         
           conn = JdbcUtils.getConnection();
           
           String sql = "select * from users where id = ?"; // 编写SQL
            st = conn.prepareStatement(sql); // 预编译
            st.setInt(1,2); //传递参数
            rs = st.executeQuery(); //执行
            if (rs.next()){
                            System.out.println(rs.getString("NAME"));            
                            }
        } catch (SQLException e) {           
         e.printStackTrace();        
         } finally {         
            JdbcUtils.release(conn,st,rs);   
                 }   
                  } 
                  }

5、防止SQL注入

import com.kuang.lesson02.utils.JdbcUtils;
import java.sql.*;
public class SQL注入 {
    public static void main(String[] args) {
        // login("lisi","123456");        
        login("'' or 1=1","123456"); //
    }
    // 登录业务
  public static void login(String username,String password){
        Connection conn =null;        
        PreparedStatement st = null;        
        ResultSet rs = null;        
        try {           
         conn = JdbcUtils.getConnection();            
         // PreparedStatement 防止SQL注入的本质,把传递进来的参数当做字符            
         // 假设其中存在转义字符,比如说 ' 会被直接转义            String sql = "select * from users where `NAME`=? and `PASSWORD`=?"; // Mybatis
            
            st = conn.prepareStatement(sql);            
            st.setString(1,username);            
            st.setString(2,password);
            rs = st.executeQuery(); //查询完毕会返回一个结果集            


            while (rs.next()){                
            System.out.println(rs.getString("NAME"));                
            System.out.println(rs.getString("password"));                
            System.out.println("============================");            }
        } catch (SQLException e) {            
        e.printStackTrace();        
        } finally {            
        JdbcUtils.release(conn,st,rs);        
        }
    }
}

7 使用IDEA连接数据库

在这里插入图片描述

如果TestConnection点不了,点击下图所示download

在这里插入图片描述
在这里插入图片描述
双击数据库
在这里插入图片描述

更新数据
在这里插入图片描述
在这里插入图片描述

链接失败,查看原因

在这里插入图片描述

8 事务

要么都成功,要么都失败

ACID原则

隔离性:多个进程互不干扰
持久性:一旦提交不可逆,持久化到数据库了

隔离性的问题:
脏读:一个事务读取了另一个没有提交的事务
不可重复读:在同一个事务内,重复读取表中的数据,表数据发生了改变
虚读(幻读):在一个事务内,读取到了别人插入的数据,导致前后读出来结果不一

代码实现

1、开启事务 conn.setAutoCommit(false);
2、一组业务执行完毕,提交事务
3、可以在catch 语句中显示的定义 回滚语句,但默认失败就会回滚

import java.sql.Connection; 
import java.sql.PreparedStatement; 
import java.sql.ResultSet; 
import java.sql.SQLException;
public class TestTransaction2 {
    public static void main(String[] args) { 
           Connection conn = null;        
           PreparedStatement st = null;        
           ResultSet rs = null;               
           try {        
               conn = JdbcUtils.getConnection();            // 关闭数据库的自动提交,自动会开启事务            
               conn.setAutoCommit(false); // 开启事务
            
               String sql1 = "update account set money = money-100 where name = 'A'";            
               st = conn.prepareStatement(sql1);            
               st.executeUpdate();
             
               int x = 1/0; // 报错
               String sql2 = "update account set money = money+100 where name = 'B'";            
               st = conn.prepareStatement(sql2);            
               st.executeUpdate();
            //业务完毕,提交事务            

                conn.commit();            
                System.out.println("成功!");
        } catch (SQLException e) {
            // 若果失败,则默认回滚 
            //            try { 
            //                conn.rollback();  
            // 如果失败则回滚事务 
            //            } catch (SQLException e1) { 
            //                e1.printStackTrace(); //            
            }            
            e.printStackTrace();        
            } finally {         
               JdbcUtils.release(conn,st,rs);        
            }
    } 

9 .数据库连接池

数据库连接 — 执行完毕 — 释放
连接 – 释放 十分浪费系统资源
池化技术:准备一些预先的资源,过来就连接预先准备好的

最小连接数: 10
最大连接数: 15
等待超时:100ms

开源数据源实现 ( 拿来即用 )

DBCP
C3P0
Druid:阿里巴巴
使用了这些数据库连接池之后,我们在项目开发中就不需要编写连接数据库的代码了!

DBCP

需要用到的 jar 包 commons-dbcp-1.4 、 commons-pool-1.6

C3P0

需要用到的 jar 包
c3p0-0.9.5.5、mchange-commons-java-0.2.19

结论

无论使用什么数据源,本质还是一样的,DataSource接口不会变,方法就不会变

发布了80 篇原创文章 · 获赞 7 · 访问量 4772

猜你喜欢

转载自blog.csdn.net/y18791050779/article/details/104829511