JDBC(一)JDBC简介,JDBC连接工具类的封装,主键回显,一次性多条数据插入,数据库连接池,SQL注入问题

一、JDBC简介

1.1 JDBC概念

  1. jdbc(java Database Connectivity)java连接数据库的规范(标准),可以使用java语言连接数据库完成CRUD操作

1.2 JDBC的核心思想

  1. java中定义了访问数据库的接口,可以为多种关系型数据库提供统一的访问方式。由数据库厂商提供驱动实现类(Driver数据库驱动)
  2. 在这里插入图片描述

二、JDBC连接工具类的封装

2.1 代码演示

package Utils;

import java.sql.*;

/**
 * 数据库连接工具类
 * 懒汉设计模式
 *
 * @author peanut
 */
public class ConnectionUtilityClass {

    private static ConnectionUtilityClass cuc;

    private static Connection conn;

    private ConnectionUtilityClass() {
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            String url = "jdbc:mysql://localhost:3306/qf?characterEncoding=utf-8&serverTimezone=UTC&useSSL=false";
            String username = "数据库用户名";
            String password = "数据库密码";
            conn = DriverManager.getConnection(url, username, password);
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }
    }

    public static Connection getConnection() {
        synchronized (ConnectionUtilityClass.class) {
            if (cuc == null) {
                cuc = new ConnectionUtilityClass();
            }
            return conn;
        }
    }

    public static Boolean closeConnection(ResultSet rs, Statement st) {
        synchronized (ConnectionUtilityClass.class) {
            try {
                if (rs != null) {
                    rs.close();
                }
                if (st != null) {
                    st.close();
                }
                if (conn != null) {
                    conn.close();
                    //关闭连接后,把工具类对象设置为空,以便下次重新连接
                    cuc = null;
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
                return false;
            }
            return true;
        }
    }
}

三、主键回显

3.1 问题的产生

  1. 例如:有A、B 两个表,B表保存A表的主键,并且A表的主键设置为自增,如何当A表插入数据时,同时返回A表主键插入B表

3.2 问题解决

  1. 代码实现
package Demo03;

import Utils.ConnectionUtilityClass;

import java.sql.*;

public class MethodSet {

    public void insertData() {
        Connection conn;
        PreparedStatement ps = null;
        ResultSet keys = null;
        try {
            conn = ConnectionUtilityClass.getConnection();
            //设置插入时返回主键最后keys
            ps = conn.prepareStatement("insert into students(username,password) values (?,?)", Statement.RETURN_GENERATED_KEYS);
            ps.setString(1, "曹操");
            ps.setString(2, "123");
            ps.executeUpdate();
            //返回结果集
            keys = ps.getGeneratedKeys();
            while (keys.next()) {
                //获取数据库第一列的第一个(后面开始)
                int anInt = keys.getInt(1);
                ps = conn.prepareStatement("insert into book (name,stuid) values (?," + anInt + ")");
                ps.setString(1, "bb");
                ps.executeUpdate();
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            ConnectionUtilityClass.closeConnection(keys, ps);
        }
    }
}

  1. 测试类
package Demo03;

/**
 * 主键回显
 * @author peanut
 */
public class Test {
    public static void main(String[] args) {
        MethodSet methodSet = new MethodSet();
        methodSet.insertData();
    }
}

四、一次性多条数据插入

  1. 实体类
package Demo02.model;

public class Student {
    private String username;
    private String password;

    public Student() {
    }
    ;

    public Student(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "Student{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

  1. Dao类
package Demo02.Dao;
import Demo02.model.Student;
import Utils.ConnectionUtilityClass;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;

/**
 * 数据库操作方法工具集
 *
 * @author peanut
 */
public class MethodSet {
    /**
     * @Description 一次性插入多条数据
     * @Return void
     * @Method_name insertMultipleData
     * @Param [list]
     */
    public void insertMultipleData(List<Student> list) {
        Connection conn;
        PreparedStatement ps = null;
        conn = ConnectionUtilityClass.getConnection();
        try {
            ps = conn.prepareStatement("insert into students (username,password) values (?,?)");
            for (int i = 0; i < list.size(); i++) {
                ps.setString(1, list.get(i).getUsername());
                ps.setString(2, list.get(i).getPassword());
                ps.addBatch();
            }
            int[] ints = ps.executeBatch();
            if (ints.length == list.size()) {
                System.out.println("成功插入:" + ints.length + "条");
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            ConnectionUtilityClass.closeConnection(null, ps);
        }
    }
}

  1. 测试类
package Demo02;
import Demo02.Dao.MethodSet;
import Demo02.model.Student;
import java.util.ArrayList;
import java.util.List;

/**
 * 批量插入
 */
public class Test {
    public static void main(String[] args) {
        MethodSet ms = new MethodSet();
        List<Student> list = new ArrayList<>();
        list.add(new Student("夏利", "123"));
        list.add(new Student("夏利", "123"));
        list.add(new Student("夏利", "123"));
        list.add(new Student("夏利", "123"));
        list.add(new Student("夏利", "123"));
        ms.insertMultipleData(list);
    }
}

五、数据库连接池

5.1 连接池的封装

package Demo04;

import com.alibaba.druid.pool.DruidDataSource;

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


/**
 * 单例模式-饿汉设计模式
 * @author peanut
 */
public class ConnectionPool{

    private static DruidDataSource ds = null;

    /**
     *禁止外部创建对象
     */
    private ConnectionPool(){};

    //加载时创建
    static {
        //创建一个数据库连接池
        ds = new DruidDataSource();
        //设置数据库连接驱动
        ds.setUrl("jdbc:mysql://localhost:3306/qf?characterEncoding=utf-8&serverTimezone=UTC&useSSL=false");
        //设置数据库用户名
        ds.setUsername("数据库用户名");
        //设置数据库密码
        ds.setPassword("数据库密码");
        //初始化数据库连接数,开始连接数为100条
        ds.setInitialSize(100);
        //设置空闲时数据库最小连接数,当目前没有人使用connection连接时,连接池也会有50个待命连接
        ds.setMinIdle(50);
        //设置最大等待时间1分钟,当所有的connection连接都被使用时,在等待获取连接期间最多等待一分钟就会抛出异常
        ds.setMaxWait(1000*60);
        //连接池最大连接数,连接池最大连接200个connection
        ds.setMaxActive(200);
    }

    /**
     * 获取一个connection连接对象
     * @return
     */
    public static Connection getConnection() {
        synchronized (ConnectionPool.class) {
            if (ds != null) {
                try {
                    return ds.getConnection();
                } catch (SQLException throwables) {
                    throwables.printStackTrace();
                }
            }
            return null;
        }
    }

    /**
     * 关闭连接
     * @param rs
     * @param st
     * @param conn
     * @return
     */
    public static boolean closeConnection(ResultSet rs, Statement st,Connection conn){
        synchronized (ConnectionPool.class) {
            try {
                if (rs != null) {
                    rs.close();
                }
                if (st != null) {
                    st.close();
                }
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
                return false;
            }
        }
        return true;
    }
}

5.2 测试类

package Demo04;

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

public class Test01 {
    public static void main(String[] args) {
        //获取一条连接
        Connection conn = ConnectionPool.getConnection();
        if (conn != null) {
            PreparedStatement ps = null;
            try {
                ps = conn.prepareStatement("insert into students (username,password) values (?,?)");
                ps.setString(1,"小凡凡");
                ps.setString(2,"asd");
                int i = ps.executeUpdate();
                if (i > 0) {
                    System.out.println("更新成功:" + i);
                }
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            } finally {
                //关闭连接
                ConnectionPool.closeConnection(null, ps, conn);
            }
        }else {
            System.out.println("获连接为空");
        }
    }
}

六、SQL注入问题

6.1 SQL注入问题的描述

  1. 用户输入的数据中有SQl关键字或语法并且参与了SQL语句的编译,导致结果为true,一直得到正确的结果

6.2 解决方法

  1. 解决:在输入数据前进行对SQL语句的预编译,然后再进行填充数据,填充进去的数据无论是啥都为数值,如sql关键字将被转义
  2. 使用PreparedStatement 继承了 Statement 接口,执行 SQL 语句的方法无异
  3. PreparedStatement作用
    A.预编译SQL语句,效率高
    B.避免SQL注入,安全
    C.可以动态的的填充数据,执行多个同构SQL语句
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

IT阿生

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

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

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

打赏作者

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

抵扣说明:

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

余额充值