JDBC(重点)

10、JDBC(重点)

java操作数据库

10.1、数据库驱动

驱动:声卡、显卡、数据库
在这里插入图片描述
我们的程序会通过 数据库驱动,和数据库打交道!

10.2、JDBC

SUN公司为了简化 开发人员的(对数据库的统一)操作,提供了一个(java操作数据库的)规范 ,俗称 JDBC

用这个驱动去连数据库的

这些规范的实现由具体的厂商去做~

对于开发人员来说,我们只需要掌握JDBC接口的操作即可

在这里插入图片描述
编写这个需要两个包:

java.sql

javas.sql

还需要导入一个数据库驱动包 :

https://mvnrepository.com/artifact/mysql/mysql-connector-java

驱动下载:

https://downloads.mysql.com/archives/c-j/

10.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,'zhangsan','123456','zs@sina.com','1980-12-04'),
(2,'lisi','123456','lisi@sina.com','1981-12-04'),
(3,'wangwu','123456','wangwu@sina.com','1979-12-04');

1、创建一个普通项目

2、导入数据库驱动

在这里插入图片描述
在这里插入图片描述

3、编写测试代码

package com.yin.lesson01;

import java.sql.*;

public class JdbcFirstDemo01 {

    public static void main(String[] args) throws ClassNotFoundException, SQLException {

        //1.加载驱动
        Class.forName("com.mysql.cj.jdbc.Driver");
        //2.用户信息和url
            //连接第一个参数用?
            // useUnicode=true:支持中文编码
            // characterEncoding=utf8:设置字符集为utf8
            // useSSL=true:使用安全的连接
            // serverTimezone=UTC:MySQL8.0以后加上时区
        String url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=UTC";
        String username ="root";
        String password ="123456";
        //3.连接成功,数据库对象
            // DriverManager:驱动管理
            // getConnection:获得连接
            // connection:代表数据库
        Connection connection = DriverManager.getConnection(url, username, password);
        //4.执行sql的对象
            // Statement:执行sql的对象
        Statement statement = connection.createStatement();

        //5.执行sql的对象 去执行sql ,可能存在结果,查看返回结果
        String sql ="select * from users";

            //execute()  :执行
            //executeQuery():查询
            //executeUpdate():更新(增删改)
        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();

    }

}


id=1
name=zhangsan
pwd=123456
email=zs@sina.com
birth=1980-12-04
================================
id=2
name=lisi
pwd=123456
email=lisi@sina.com
birth=1981-12-04
================================
id=3
name=wangwu
pwd=123456
email=wangwu@sina.com
birth=1979-12-04
================================

进程已结束,退出代码为 0

package com.kuang.lesson01;

import java.sql.*;

//  我的第一个JDBC程序
public class jdbcFirstDemo {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
//        1.加载驱动
//             DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver());
            Class.forName("com.mysql.cj.jdbc.Driver");  // 固定写法,加载驱动
//        2.用户信息和url
//                            连接数据库了
//                                             连接第一个参数用:?
//        这个三个参数的意思:?useUnicode=true&charcaterEncoding=utf8&useSSL=true
//        ?useUnicode=true   支持中文编码
//        charcaterEncoding=utf8    设置它得字符集为utf-8
//        useSSL=true           使用安全的链接      //  &serverTimezone=GMT%2B8
            String url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&charcaterEncoding=utf8&useSSL=true&serverTimezone=UTC ";
            String username = "root";
            String password = "123456";
//        3.连接成功,返回数据库对象        Connection 代表数据库
        Connection connection = DriverManager.getConnection(url, username, password);
       /* connection.rollback(); //设置回滚
        connection.commit(); //提交
        connection.setAutoCommit();//自动提交*/


//        4.执行SQL的对象        Statement 执行SQL的对象
        Statement statement = connection.createStatement();

        /*statement.executeQuery();  //查询操作 返回 结果集ResultSet
        statement.execute();        //执行任何SQL
        statement.executeUpdate(); // 更新、插入、删除。都使用这个,返回一个受影响的行数*/

//        5.执行SQL的对象 去 执行SQL ,一般执行完SQL可能存在结果,查看返回结果
//
        String sql = "select * from users";
//        execute()  :执行
//        executeQuery() :查询
//        executeUpdate() :更新  所有的删除和插入都叫做更新,
        ResultSet resultSet = statement.executeQuery(sql);  // 返回一个结果集

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

/*//        遍历,指针
        resultSet.beforeFirst(); //移动到最前面
        resultSet.afterLast();//移动到最后面
        resultSet.next();//移动到下一个数据
        resultSet.previous();//移动到前一行
        resultSet.absolute(row);//移动到指定行*/
//        查看返回的东西
        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();//耗资源,用完关掉

        Statement st = connection.createStatement();
//        String sql ="delete from u";

    }
}

步骤总结:

1、加载驱动 Class.forName(“com.mysql.cj.jdbc.Driver”); // 固定写法,加载驱动

2、连接数据库 DriverManager

3、获取执行sql的对象 statement (以后写了方法后,只用往这里传一个sql就可以)

4、获得返回的结果集(resultSet) 查询才有结果集 ,剩下的是受影响的行数

5、释放连接

解释 常用的对象

DriverManager(驱动管理)

		//  1.加载驱动
		//DriverManager.registerDriver(new com.mysql.cj.jdbc.Driver());
 		Class.forName("com.mysql.cj.jdbc.Driver");  // 固定写法,加载驱动

    Connection connection = DriverManager.getConnection(url, username, password);   //推荐使用这种
		//connection 代表数据库
		//作用?
		//数据库设置自动提交
		//事务提交
		//事务回滚
       
       //代表数据库能做的一些事情
        connection.rollback(); //设置回滚
        connection.commit(); //提交
        connection.setAutoCommit();//自动提交

URL(地址)

		//?useUnicode=true   支持中文编码
		//charcaterEncoding=utf8    设置它得字符集为utf-8
		//useSSL=true           使用安全的链接
String url = "jdbc:mysql://localhost:3306/com/jdbcstudy?useUnicode=true&charcaterEncoding=utf8&useSSL=false&serverTimezone=UTC";

		// mysql 默认 3306
		//String url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=UTC";
 		//公式:// 协议://主机地址:端口号/数据库名?参数1&参数2&参数3

// oralce 默认 -- 1521 
// oralce(写法)
// 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();
        ....

遍历,next()指针

//[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1] 
resultSet.beforeFirst(); //移动到最前面
 resultSet.afterLast();//移动到最后面
 resultSet.next();//移动到下一个数据 常用
 resultSet.previous();//移动到前一行
 resultSet.absolute(row);//移动到指定行

释放资源(必须做)

连接占用内存!

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

10.4、statement对象

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

Statement对象的executeUpdate方法,用于向数据库发送增、删、改的sql语句,

executeUpdate执行完后,将会返回一个行数(即增删改语句导致了数据库几行数据发生了变化)。

Statement.executeQuery方法用于向数据库发送查询语句,

executeQuery方法返回代表查询结果的RseultSet对象。

CRUD操作-creat 增

使用executeUpdate(String sql)方法完成数据添加操作,识里操作:

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

CRUD操作-delete 删

使用executeUpdate(String sql)方法完成数据删除操作,

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 改

使用executeUpdate(String sql)方法完成数据修改操作

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

CRUD操作 - read 查

使用executeQuery(String sql)方法完成数据查询操作

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

代码实现 增删改查

1、提取工具类

db.properties

driver=com.mysql.cj.jdbc.Driver
#url=jdbc:mysql://localhost:3306/:端口号,这样就连接数据库了
url=jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&charcaterEncoding=utf8&useSSL=true&serverTimezone=UTC
username=root
password=123456

读取配置文件

package com.yin.lesson02.utils;
//工具类

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 {
            // getClassLoader:获得类加载器
            // getResourceAsStream:拿到他的资源,获取具体资源,资源名字文件名
            InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
            //把流读到 Properties 里
            Properties properties = new Properties();
            //把流加载进来
            properties.load(in);

            //获取对象
            driver = properties.getProperty("driver");
            url = properties.getProperty("url");
            username = properties.getProperty("username");
            password = properties.getProperty("password");

            //驱动只用加载一次
            Class.forName(driver);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //获取连接
        //简写
    public static Connection getConnection() throws SQLException {
        return  DriverManager.getConnection(url, username, password);

    }
    //释放连接资源
        // Connection:数据库连接对象
        // Statement:执行操作sql的对象
        // ResultSet:返回的结果集
    public static void release(Connection con, 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 ( con != null){
            try {
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }



}

2、编写增删改的方法,

都使用executeUpdate

package com.kuang.lesson02;

import com.kuang.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

//          插入一条数据
//              增
public class TextInsert {
    public static void main(String[] args) {

//                  获取连接
//        把 Connection 拿到最上面去
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;
				
      	//环绕方式快捷键:Ctrl + Alt + T
        try {
            conn = JdbcUtils.getConnection();//1.获取数据库连接
//            2、通过连接去创建 Statement 对象
           st= conn.createStatement();//获得SQL的执行对象
//            3、编写一个要执行SQL的命令
            String sql="insert into users(id,`NAME`,`PASSWORD`,`email`,`birthday`)" +
                    "values (4,'xiaoyin','12345','123456@qq.com','2001-04-06')";
//           4、 通过这个执行对象去执行SQL
            int i = st.executeUpdate(sql);
            if (i>0){
                System.out.println("插入成功!");
            }

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {//在这个地方释放
//            5、最后把资源释放掉
            JdbcUtils.release(conn,st,rs);
        }

    }
}

package com.kuang.lesson02;

import com.kuang.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class TextDelete {
//              删
    public static void main(String[] args) {

//                  获取连接
//        把 Connection 拿到最上面去
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection();//1.获取数据库连接
//            2、通过连接去创建 Statement 对象
            st= conn.createStatement();//获得SQL的执行对象
//            3、编写一个要执行SQL的命令
            String sql=" delete from users where id = 4";
//           4、 通过这个执行对象去执行SQL
            int i = st.executeUpdate(sql);
            if (i>0){
                System.out.println("删除成功!");
            }

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {//在这个地方释放
//            5、最后把资源释放掉
            JdbcUtils.release(conn,st,rs);
        }

    }
}

package com.kuang.lesson02;

import com.kuang.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class TestUpdate {
//                更
    public static void main(String[] args) {


//                  获取连接
//        把 Connection 拿到最上面去
        Connection conn = null;
        Statement st = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection();//1.获取数据库连接
//            2、通过连接去创建 Statement 对象
            st= conn.createStatement();//获得SQL的执行对象
//            3、编写一个要执行SQL的命令
            String sql="update users set `NAME`='xaioming',`email`='123456@qq.com' where id =1";
//           4、 通过这个执行对象去执行SQL
            int i = st.executeUpdate(sql);
            if (i>0){
                System.out.println("更新成功!");
            }

        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {//在这个地方释放
//            5、最后把资源释放掉
            JdbcUtils.release(conn,st,rs);
        }

    }
}

3、查询

executeQuery

package com.kuang.lesson02;

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;

//        1.获取连接
        try {
            conn= JdbcUtils.getConnection();
//            获取一个执行对象
            st= conn.createStatement();

//            写SQL
//            输出全部的
//            String sql = "select *from users ";

            String sql = "select *from users where id=1";

//            会返回一个结果集,执行一下
            rs= st.executeQuery(sql); //查询完毕会返回一个结果集

//            打印
            if (rs.next()){
//                只会输出一号用户的名字
                System.out.println(rs.getString("NAME"));
                System.out.println(rs.getString("password"));
                System.out.println("===================");
            }



        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
        //释放资源
        finally {
            JdbcUtils.release(conn,st,rs);
        }

    }
}

SQL注入的问题

什么叫SQL注入?

sql 存在漏洞,会被攻击导致数据泄露,本质:SQL会被拼接 ,有or的原因!

package com.yin.lesson02;

import com.yin.lesson02.utils.JdbcUtils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

//SQL注入问题
public class SQLInjection {
    public static void main(String[] args) {

        //login("xiaoying","123456"); 正常登录

        //SQL注入!
        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` = 'xiaoying' 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.getObject("name"));
                System.out.println(rs.getObject("password"));
                System.out.println("=============");
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.release(conn,st,rs);
        }


    }
}
xiaoying
123456
=============
lisi
123456
=============
wangwu
123456
=============
xiaiobai
123456
=============

进程已结束,退出代码为 0

10.5、PreparedStatement对象

它和 statement对象 本质的区别是:

PreparedStatement对象可以防止SQL注入,并且效率更高!

**PreparedStatement本质:**把传递进来的参数当做字符

代码实现

步骤
  1. 获取连接 获取数据库的连接对象
  2. 写sql执行的命令
  3. 通过连接创建 prepareStatement 对象 (操作sql的对象)
  4. 手动给参数赋值赋值 (参数的下标,具体的值)
  5. 执行sql
  6. 打印出来
  7. 关闭连接
1、新增
package com.yin.lesson03;

import com.yin.lesson02.utils.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 {
            //1.获取连接  获取数据库的连接对象
            conn = JdbcUtils.getConnection();

                // 和Statement的区别:
                // 使用? 占位符替代参数
            //2.写sql执行的命令
            String sql = "insert into users(id,`NAME`,`PASSWORD`,`email`,`birthday`) value (?,?,?,?,?)";
            //3.通过连接创建 prepareStatement 对象 (操作sql的对象)
            st = conn.prepareStatement(sql); //预编译SQL,先写sql,先不执行
            //4.手动给参数赋值赋值
            st.setInt(1,5);
            st.setString(2,"xiaoming");
            st.setString(3,"123456");
            st.setString(4,"1455272942@qq.com");
                // 注意点:
                // sql.Date: 数据库的  java.sql.Date()
                // util.Date: Java的  new Date().getTime() 获得时间戳
            st.setDate(5,new java.sql.Date(new Date().getTime()));
            //5.执行sql
            int i = st.executeUpdate();
            if (i>0){
                System.out.println("插入成功");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.release(conn,st,null);
        }
    }
}
插入成功
2、删除
package com.yin.lesson03;

import com.yin.lesson02.utils.JdbcUtils;

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

//删除
public class TestDelete {

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

        //1.获取数据库的连接
        try {
            conn = JdbcUtils.getConnection();
        //2.编写sql代码
            String sql = "delete from users where id = ?";
        //3.创建 PreparedStatement 操作数据库对象
            st = conn.prepareStatement(sql);
        //4.手动给参数赋值
            st.setInt(1,5);
        //5.执行sql
            int i = st.executeUpdate();
            if (i>0){
                System.out.println("删除成功!");
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
        //6.关闭连接
            JdbcUtils.release(conn,st,null);
        }
    }
}
删除成功
3、更新
package com.yin.lesson03;

import com.yin.lesson02.utils.JdbcUtils;

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

//修改

//1.获取数据库连接
//2.编写sql语句
//3.创建执行数据库的对象 PreparedStatement
//4.手动赋值
//5.执行sql
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` = ?,`email`= ? where id = ?";
            st = conn.prepareStatement(sql);
            st.setString(1,"xiaobai");
            st.setString(2,"1455272942@qq.com");
            st.setInt(3,1);
            int i = st.executeUpdate();
            if (i>0){
                System.out.println("修改成功!");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.release(conn,st,null);
        }

    }
}
修改成功!
4、查询
package com.yin.lesson03;

import com.yin.lesson02.utils.JdbcUtils;

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

//查
/*
1.获取数据库连接
2.编写sql的命令
3.创建操作数据库的对象 PreparedStatement
4.给数据库参数赋值 (参数的下标,具体的值)
5.执行sql
6.关闭连接
 */
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 = ?";
            st = conn.prepareStatement(sql);
            st.setInt(1,1);
            rs = st.executeQuery();
            while (rs.next()){
                System.out.println(rs.getInt("id"));
                System.out.println(rs.getString("name"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.release(conn,st,rs);
        }
    }
}
1
xiaobai

5、防止SQL注入
package com.yin.lesson03;

import com.yin.lesson02.utils.JdbcUtils;

import java.sql.*;
/*
步骤:
1.获得数据库连接
2.编写sql代码
3.创建操作数据库的类 PreparedStatement
4.给数据库参数赋值
5.执行sql
6.打印出来
7.关闭连接
 */

public class SQLInjection {

    public static void main(String[] args) {

        //正常登录
        login("wangwu","123456");

        //SQL注入!
//        login("'or'1=1"," 'or'1=1");//有技巧的输入

    }

    //登录功能
    public static void login(String username ,String password){

        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection();
            String sql = "select * from users where `name` =?  and `password` = ?" ;
            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"));
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.release(conn,st,rs);
        }
    }

}
wangwu
123456

10.7、使用IDEA连接数据库

在这里插入图片描述
2、连接成功后选择数据库
在这里插入图片描述
在这里插入图片描述

查看数据库内容:

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

在这里插入图片描述

更新数据

在这里插入图片描述
在这里插入图片描述

编写sql代码

在这里插入图片描述

注意

时区

8.0以后的版本把serverTimezone设置为:

  • Asia/Shanghai
  • UTC
MySQL版本
  • 8.0版本使用:com.mysal.cj.jdbc.Driver
  • 5.0版本使用:com.mysql.jdbc.Driver

如果版本不对,导致连接失败修改位置
在这里插入图片描述
在这里插入图片描述

路径

不要乱改
在这里插入图片描述

10.8、事务

要么都成功,要么都失败

ACID原则

原子性:要么都成功,要么都失败

一致性:总数不变

隔离性:多个进程互补干扰

持久性:一旦提交不可逆,持久化到数据库了

隔离性的问题:

脏度:一个事务读取了另一个没有提交的事务

不可重复读:在同一个事务内,重复读取表中的数据,表数据发生了改变

虚度(幻读):在一个事务内,读取到了别人插入的数据,导致前后读出的结果不一致(隔离性问题)

转账

代码实现

1、开启事务 : conn.setAutoCommit(false);

2、一组业务执行完毕,提交事务 :****conn.commit();

3、可以在catch 语句中显示的定义 回滚语句,但默认失败就会回滚 conn.rollback();

成功的

package com.yin.lesson04;

import com.yin.lesson02.utils.JdbcUtils;

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

//模拟转账! 成功的
public class TestTransaction1 {
    public static void main(String[] args) {

        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;

        try {
            conn = JdbcUtils.getConnection();
            // 关闭数据库的自动提交,会自动开启事务
            conn.setAutoCommit(false);// 开启事务
            // 执行sql

            // 模拟执行成功的
            String sql1 = "Update account set money = money - 100 where name = 'A'";
            st = conn.prepareStatement(sql1);
            st.executeUpdate();
            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 ex) {
                ex.printStackTrace();
            }
            e.printStackTrace();
        } finally {
            JdbcUtils.release(conn,st,rs);

        }

    }
}

失败的

package com.yin.lesson04;

import com.yin.lesson02.utils.JdbcUtils;

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 ex) {
                ex.printStackTrace();
            }
            e.printStackTrace();
        } finally {
            JdbcUtils.release(conn,st,rs);
        }
    }
}

10.9、数据库连接池

数据库连接 – 执行完毕 – 到 释放

连接-–> 释放 是十分浪费系统资源的

池化技术: 准备一些预先的资源,过来就连接预先准备好的

  • 讲解:我们每次去连接,去执行10个SQL,需要每次连接释放十次,预留下来五个接口

举例假设:银行

没有池化技术:

  • ----开门 – 服务(自己)---- 关门 — 很麻烦

有池化技术:

  • -----开门 ---- 业务员(等待)------服务 ----- 关门(服务器关闭)

涉及到的问题:一个银行需要几个业务员?

  • 按照常用连接数设置:最小连接数!

    • 最小连接数如:10
  • 一般情况下设置:最大连接数!

    • 最大连接数如:15 业务最高承载上限
  • 假设15个员工都被用了,需要排队等待!

  • 等待这15个人有人用完了在可以再用!

  • 等待超时:

    • 假设等待超过了100ms,断开

编写连接池

只需要实现一个接口 DataSource

对于它的实现类,世界上比较知名的有:

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

DBCP(开源组织实现的)

C3P0(开源组织实现的)

Druid:(阿里巴巴的)

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

DBCP

需要用到的 jar 包

  • commons-dbcp-1.4

  • commons-pool-1.6

创建 :dbcpconfig.properties 配置文件

#连接设置 这里面的名字,是DBCP数据源定义好的
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbcstudy?serverTimezone=GMT&useUnicode=true&charcaterEncoding=utf8&useSSL=true&serverTimezone=Asia/Shanghai
username=root
password=123456

#!-- 初始化连接 --
initialSize=10

#最大连接数量
maxActive=50

#!-- 最大空闲连接 -- 用完之后,先不释放,等待超时之后,再释放!

maxIdle=20

#!-- 最小空闲连接 --
minIdle=5

#!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60--
maxWait=60000
#JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:【属性名=property;】
#注意:user 与 password 两个属性会被明确地传递,因此这里不需要包含他们。
connectionProperties=useUnicode=true;characterEncoding=UTF8

#指定由连接池所创建的连接的自动提交(auto-commit)状态。
defaultAutoCommit=true

#driver default 指定由连接池所创建的连接的只读(read-only)状态。
#如果没有设置该值,则“setReadOnly”方法将不被调用。(某些驱动并不支持只读模式,如:Informix)
defaultReadOnly=

#driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。
#可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED,READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
defaultTransactionIsolation=READ_UNCOMMITTED

创建:工具类

package com.yin.lesson05;

import com.yin.lesson02.utils.JdbcUtils;
import com.yin.lesson05.utils.JdbcUtils_DBCP;

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

//在并发情况下一般使用数据源!
public class TestDBCP {

    public static void main(String[] args) {

        Connection conn = null;
        PreparedStatement st = null;

        try {
            //1.获取连接  获取数据库的连接对象

            conn = JdbcUtils_DBCP.getConnection();

            // 和Statement的区别:
            // 使用? 占位符替代参数
            //2.写sql执行的命令
            String sql = "insert into users(id,`NAME`,`PASSWORD`,`email`,`birthday`) value (?,?,?,?,?)";
            //3.通过连接创建 prepareStatement 对象 (操作sql的对象)
            st = conn.prepareStatement(sql); //预编译SQL,先写sql,先不执行
            //4.手动给参数赋值赋值
            st.setInt(1,5);
            st.setString(2,"xiaoming");
            st.setString(3,"123456");
            st.setString(4,"1455272942@qq.com");
            // 注意点:
            // sql.Date: 数据库的  java.sql.Date()
            // util.Date: Java的  new Date().getTime() 获得时间戳
            st.setDate(5,new java.sql.Date(new Date().getTime()));
            //5.执行sql
            int i = st.executeUpdate();
            if (i>0){
                System.out.println("插入成功");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils_DBCP.release(conn,st,null);
        }
    }
}

插入类

package com.yin.lesson05.utils;

import com.yin.lesson02.utils.JdbcUtils;
import org.apache.commons.dbcp.BasicDataSourceFactory;

import javax.sql.DataSource;
import java.io.InputStream;
import java.nio.file.attribute.BasicFileAttributes;
import java.sql.*;
import java.util.Properties;

public class JdbcUtils_DBCP {

    // 数据源
    private static DataSource dataSource = null;


    static {

        try {
            // getClassLoader():获得类加载器
            // getResourceAsStream():拿到他的资源,获取具体资源,资源名字文件名
            InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");
            //把流读到 Properties 里
            Properties properties = new Properties();
            // 把流加载进来
            properties.load(in);

            // 创建数据源
                // BasicDataSourceFactory:工厂模式 --> 创建对象的
                // 返回数据源
            dataSource = BasicDataSourceFactory.createDataSource(properties);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //获取连接 数据源里边自带连接
    //简写
    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection(); // 从数据源中获取连接
    }

    //释放连接资源
        // Connection:数据库连接对象
        // Statement:执行操作sql的对象
        // ResultSet:返回的结果集
    public static void release(Connection con, 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 ( con != null){
            try {
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

C3P0

需要用到的 jar 包

  • c3p0-0.9.5.5

  • mchange-commons-java-0.2.19

结论

无论使用什么数据源,本质还是一样的

DataSource 接口不会变,工具类中的方法就不会变

//    获取连接
    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();//从数据源中获取连接  getConnection:接口的方法
    }
Druid
  • stringboot学习

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小尹^_^

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值