【无标题】

day10-JDBC

一 、JDBC的简介

1.JDBC(Java Database Connectivity)Java连接数据库的规范,使用Java代码来实现数据库的CRUD(数据库的增删查改)操作

二、JDBC的核心思想

1.java里面第一一些访问数据库的接口,提供访问多种数据库的统一的访问的方法,由数据库厂商提供数据库的驱动实现类

三、MySQL的驱动

mysql数据库的版本是5.5的,数据库的驱动:mysql-connector-java-5.1.27.jar

这是一个Java的包,需要导入java项目

3.1java里面的数据库驱动
1.需要在这个java项目里面创建安装包的目录:一般为lib,把数据库的驱动包放在里面,解压出来
2.在编写java代码连接数据库的时候,数据库版本低的先写数据库驱动
	Class.forName("com.mysql.jdbc.Driver");

注意点:这个是有错误的需要进行抛出或者捕获

四、连接数据库

4.1 查询数据库(一行)
package com.lt.demo02;

import java.sql.*;

public class Test01 {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        Class.forName("com.mysql.jdbc.Driver");
        //通过DriverManager.getConnection来建立数据库连接的接口
        //第一个参数:表是为jdbc的mysql数据库后面是本地的数据库库命
        //第二个参数:数据库的战账号
        //第三个参数:数据库的连接密码
        Connection con = DriverManager.getConnection("jdbc:mysql://localhost/stu", "root", "root");
        //使用Java来进行数据库语句编写,数据库语句
        Statement st = con.createStatement();
        //执行数据库语句
        ResultSet rs = st.executeQuery("select  * from student where id=2");
        //将数据库的指标指向下一行,看是否有值
        boolean next = rs.next();
        int id = rs.getInt("id");
        String name = rs.getString("name");
        int age = rs.getInt("age");
        String sex = rs.getString("sex");
        System.out.println(id+"\t"+name+"\t"+age+"\t"+sex);

        //关闭资源
        rs.close();
        st.close();
        con.close();

    }
}

在使用完数据库之后一定要关闭数据库的资源

这样查询拥有局限性,只能查询一行,
4.2 查询数据库(多行)
package com.lt.demo02;

import java.sql.*;

public class Test02 {
    public static void main(String[] args) {
        //驱动
        Connection con = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            //连接数据库  数据库为本地数据库,localhost可以省略
            con = DriverManager.getConnection("jdbc:mysql:///stu", "root", "root");
            ps = con.prepareStatement("select * from student");
            rs = ps.executeQuery();

            //使用循环来查询
            while (rs.next()){
                int id = rs.getInt("id");
                String name = rs.getString("name");
                int age = rs.getInt("age");
                String sex = rs.getString("sex");
                System.out.println(id+"\t"+name+"\t"+age+"\t"+sex);
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //关闭资源
            try {
                rs.close();
                ps.close();
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }




    }
}

4.3 数据库注入
1.数据库注入:用户写的数据库语句或者关键字参与了sql语句的编译
2.在创建连接数据时使用:
	Statement statement = con.createStatement();
    statement.executeQuery("select  * from student where id=2");
3.如何避免数据库注入问题:
	使用prepareStatement来替换上面的操作,这个他会进行预编译过程

五、prepareStatement

5.1 prepareStatement的应用
1.优点:
	A.预编译SQL语句,效率高
	B.避免了sql语句注入问题
	C.可以动态填充数据执行多个sql语句
package com.lt.demo02;

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

public class Test03 {
    public static void main(String[] args) {
        Connection con = null;
        PreparedStatement ps = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            //通过DriverManager.getConnection来建立数据库连接的接口
            con = DriverManager.getConnection("jdbc:mysql://localhost/stu", "root", "root");
            //?表示的是参数它是一个占位符一个占位符表示一个需要传的参数
            ps = con.prepareStatement("insert  into student (name,age,sex)values (?,?,?)");
            //设置参数(第一个参数表示第几个问号,第二个参数表示添加到数据库里面的参数数据类型与数据库一致)
            ps.setString(1,"法外狂徒");
            ps.setInt(2,35);
            ps.setString(3,"女");
            //提交sql语句执行
            int i = ps.executeUpdate();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //关闭资源
            try {
                ps.close();
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

5.2 删除操作
package com.lt.demo02;

import java.sql.*;
import java.util.Scanner;

public class Test04 {
    public static void main(String[] args) {
        Connection con = null;
        PreparedStatement ps = null;
        ResultSet rs = null;

        try {
            Class.forName("com.mysql.jdbc.Driver");
            //通过DriverManager.getConnection来建立数据库连接的接口
            con = DriverManager.getConnection("jdbc:mysql://localhost/stu", "root", "root");

            Scanner scanner = new Scanner(System.in);
            System.out.println("输入你要删除的数据的序号:");
            int sid = scanner.nextInt();
            //动态填充id,通过id来进行删除数据
            ps = con.prepareStatement("delete from student where id=?");
            //填充需要删除的数据
            ps.setInt(1,sid);
            int i = ps.executeUpdate();

            //查询
            ps = con.prepareStatement("select * from student");

            rs = ps.executeQuery();

            //使用循环来查询删除过后的数据库
            while (rs.next()){
                int id = rs.getInt("id");
                String name = rs.getString("name");
                int age = rs.getInt("age");
                String sex = rs.getString("sex");
                System.out.println(id+"\t"+name+"\t"+age+"\t"+sex);
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                ps.close();
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }




    }
}

结果:

在这里插入图片描述

六、封装工具类

将加载数据库连接和关闭资源封装成一个工具类方便调用

封装的工具类

package com.lt.DBUtils;

import java.sql.*;

public class DBUtils {

    //驱动
    //使用代码块,类加载执行一次
    static {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    public static Connection getConnection(){
        Connection connection=null;
        //数据库连接
        try {
            connection = DriverManager.getConnection("jdbc:mysql:///stu", "root", "root");
        } catch (SQLException  e) {
            e.printStackTrace();
        }
        return connection;
    }

    /**
     * 关闭资源
     * 需要先判断这个资源是否为空
     * @param con
     */
    public static void close(Connection con){
        try {
            if (con!=null) {
                con.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public static void close(ResultSet rs){
        try {
            if (rs!=null) {
                rs.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public static void close(PreparedStatement ps){
        try {
            if (ps!=null) {
                ps.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

使用工具类来添加数据

package com.lt.demo02;

import com.lt.DBUtils.DBUtils;

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

public class Test05 {
    public static void main(String[] args)  {

        Connection con=null;
        PreparedStatement ps=null;
        ResultSet rs = null;
        try {
            //连接
            con = DBUtils.getConnection();
            //数据库语句
            ps = con.prepareStatement("select * from student");
            //执行
            rs = ps.executeQuery();

            //查询
            //使用循环来查询
            while (rs.next()){
                int id = rs.getInt("id");
                String name = rs.getString("name");
                int age = rs.getInt("age");
                String sex = rs.getString("sex");
                System.out.println(id+"\t"+name+"\t"+age+"\t"+sex);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            //关闭
            DBUtils.close(rs);
            DBUtils.close(ps);
            DBUtils.close(con);
        }
    }
}

七、数据库Druid连接池

1.在初始化的时候预先创建连接池的数量需要连接数据库时候从数据库连接池里面拿取用完有放回去,也不会关闭,实现服用,节省资源

八、事物

1.事物:是一个原子操作,是一个最小执行单元,可以有一个或多个数据库语句组成。在同一个事物中,所有的数据库语句执行成功那么这个事物是完成的;有一个sql语句执行失败,那么整个事务是失败的
8.2 事物的边界
  • 开始: ;连接到数据库,执行一条DML语句。上一个事物完成后,开启下一条DML语句,这是事物的开启
  • 结束:
    • 提交
      • 显示提交:commit方法提交
      • 隐式提交:一条创建删除的语句正常退出(客户端退出)
    • 回滚:
      • 显示回滚:使用rollback方法回滚
      • 隐式回滚:非正常退出(断电、宕机) ,执行了创建或者删除操作,但是失败了,但是会进行回滚,
8.2 事物的特性(ACID)
1.Atomicity(原子性):
	表示一个事物内的所有操作是一个整体,要么全部成功,要么全部失败
2.Consistoncy(一致性)
	表示一个事物的一条语句执行失败,整个事务所有已经执行的操作回滚到执行之前的状态
3.Isolation(隔离性)
	事物查看数据操作时数据所处的状态要么是另外一个并发之前修改之前的状态,要么是修改之后的状态,不能查看中间的状态的数据
4.Durability(持久性)
	持久性的事物完成后,对系统的影响也是持久的
try {
            //开启事物
            con.setAutoCommit(false);
            AccountDao.addMoney("张三",50 );
//            int i = 1 / 0;
            AccountDao.minMoney("李四",50);
            //执行成功,则提交事务
            con.commit();
        } catch (SQLException e) {
            e.printStackTrace();
            try {
                //出现错误,事物回滚 
                con.rollback();
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
        } finally {
    		con
             DBUtils_01.close(con);
        }

作用:保证数据的完整性、一致性,

九、ThreadLocal

9.1 ThreadLocal简介
1.ThreadLocal	是什么?
	ThradLocal是线程Thread中的ThreadLocals的管理者
2.ThreadLocal的set、get、remove的方法的操作都是针对当前线程的实例ThreadLocal存、取、删除操作
3.ThreadLocal里面的方法:
	set(参数) 存放一个对象,参数就是存放的对象
    get() 读取一个对象
    remove() 移除对象
9.2 ThreadLocal 的使用
package com.lt.DBUtils;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

public class DBUtils_01 {
    //生明连接池对象
    private static DataSource ds=null;
    //设置成一个常量,
    private static final Properties PROPERTIES=new Properties();

    /**
     * z 特点:存储在里面的数据,是哪一条线程,就在那一条线程读取,换一个线程读取不到
     * ThreadLocal 里面可以存放一个对象,在这里,存放connection连接对象
     * ThreadLocal 有三个方法:
     */

    private static final  ThreadLocal<Connection> THREAD_LOCAL = new ThreadLocal<>();

    //使用代码块加载配置文件这样配置文件只加载一次

    /**
     * /表示从文件根部寻找这个文件
     * 这个操作表示手动想properties文件中 put了7条数据put 完成后通过properties.get(""username)来获取
     */
    static {
        try {
            PROPERTIES.load(DBUtils_01.class.getResourceAsStream("/properties.properties"));
            //根据配置文件创建一个 datasource数据源
            ds= DruidDataSourceFactory.createDataSource(PROPERTIES);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
  
    public static Connection getConnection(){
        //读取一个对象,那么THREAD_LOCAL里面只能存放这类的对象其他的存放不了
        Connection con = THREAD_LOCAL.get();
        if (con==null){
            try {
                Connection connection = ds.getConnection();
                //把连接对象存放到ThreadLocal里面
                THREAD_LOCAL.set(connection);
                return connection;
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return con;

    }

    public static void close(Connection con){

        if (con!=null){
            try {
                con.close();
                //将连接放回连接池的时候,需要THREAD_LOCAL先将里面保存的连接给移除掉不然
                // 这个链接回归到连接池后,没有人能将THREAD_LOCAL里面的连接给移除了
                THREAD_LOCAL.remove();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    public static void close(ResultSet con){
        if (con!=null){
            try {
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    public static void close(PreparedStatement con){
        if (con!=null){
            try {
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

}

十、配置文件的快捷写法

step01

在这里插入图片描述

step02

在这里插入图片描述

step 03

在这里插入图片描述

之后在需要创建配置文件的时候,快捷创建

在这里插入图片描述

十一、封装工具类的优化

package com.lt.DBUtils;

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

/**
 * THREAD_LOCAL的作用是保证connection是同一个connection连接对象
 */
public class DBUtils_02 {
    //连接池对象
    private static DataSource ds = null;
    private static final Properties PROPERTIES = new Properties();

    //在这里,是控制连接对像
    private static final ThreadLocal<Connection> THREAD_LOCAL=new ThreadLocal<>();

    //使用代码块 加载配置文件
    static {
        //使用ThreadLoacl里面的方法  jbdc.properties是文件,还有 / 是不能少 /是表是从src文件夹下面去寻找配置文件
        try {
            PROPERTIES.load(DBUtils_02.class.getResourceAsStream("/jbdc.properties"));
            //根据配置文件创建一个 datasource数据源
            ds= DruidDataSourceFactory.createDataSource(PROPERTIES);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Connection getConnection(){
        //根据读取连接对象(在创建ThreadLoacl时候声明了里面存放的对象是一个connection连接对象)
        Connection connection = THREAD_LOCAL.get();

        try {
            Connection connection1 = ds.getConnection();
            //存放对象
            THREAD_LOCAL.set(connection);
            return connection1;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }
    
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

一个胖小白

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

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

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

打赏作者

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

抵扣说明:

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

余额充值