JDBC知识总结

什么是JDBC?

JDBC的全称是 Java Database Connectivty ,它是Java和数据库之间的一座桥梁,是一种规范。各种不同类型的数据库都依赖这种规范而有着相应的实现,都是由Java类和接口组成。以下我们来介绍的是如何通过JDBC来连接MySQL数据库

使用JDBC的步骤

1、导入JDBC的MySQL实现依赖
2、进行参数配置
3、加载驱动
4、建立连接
5、创建操作数据库对象
6、使用创建好的对象执行SQL语句
7、关闭连接

连接MySQL数据库

在java.sql包下存在有一些接口:
DriverMananger类:主要用于管理驱动程序和连接数据库
Connection接口:主要用于管理建立好的数据库连接
Statement接口:主要用于执行失SQL语句
ResultSet接口:主要用于存储数据库返回的记录

通过DriverManager类和Connection接口实现连接数据库的功能。首先使用forName()方法来指定JDBC驱动的类型。指定了MySQL驱动程序后,就可以使用DriverManager类和Connection接口来连接数据库了。在DriverManager类中有一个getConnection()方法,这个方法需要为其传递3个参数,即url、user、password。
url:指定JDBC的数据源,数据源中包括了主机名或IP,端口号和数据库名。其中,localhost表示本地计算机,3306是MySQL的端口号,数据库名可以根据使用者的需求自行添加
user:MySQL数据库的用户名
password:指定用户名的密码

下面用代码简单演示:

private String url = "jdbc:mysql://127.0.0.1:3306/school?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai";
    private String userName = "root";//用户名
    private String password = "password";//密码
    private String jdbcDriver = "com.mysql.jdbc.Driver";
    private Connection connection;
    private Statement statement;

    /**
     * 与MySQL数据库建立连接
     * @throws SQLException
     */
    public void createConnection() throws SQLException {
        try {
            Class.forName(jdbcDriver);
            //登录到MySQL服务器
            connection = DriverManager.getConnection(url,userName,password);
            if(!connection.isClosed()){
                System.out.println("连接建立成功");
                statement = connection.createStatement();
            }else{
                System.out.println("连接建立失败");
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

操作MySQL数据库

连接MySQL数据库之后,就可以对MySQL数据库进行查询、插入、删除、修改等操作了。Statement/PreparedStatement对象主要用来执行SQL语句,SQL语句执行后返回的结果由ResultSet接口来管理。
一般情况下statement对象用在一种结构的SQL语句只执行一次时,而PreparedStatement对象用在同结构的SQL语句要执行多次时,这是因为PreparedStatement对象在执行SQL语句时,会先提交一个无参数的SQL语句进行编译,然后我们再给编译之后的SQL语句提交参数。这样就可以减少许多重复的编译过程,节省了我们的时间。
当使用insert/delete/update这些SQL语句时,使用executeUpdate方法来执行
当使用select语句时,使用executeQuerry方法执行
由于statement对象更容易产生SQL注入异常,我们在实际操作的时候更多的使用PreparedStatement对象来执行我们想要执行的SQL语句

查询数据:

public void selectScore(){
        String selectSql = "select stu_id,corse_id,score from score where score > ?";
        PreparedStatement pre = null;
        try {
            pre = connection.prepareStatement(selectSql);
            pre.setInt(1,80);

            ResultSet resultSet = pre.executeQuery();
            System.out.println("80分以上:");
            while(resultSet.next()){
                System.out.println("stu_id: "+resultSet.getString(1)+
                "  course_id: "+resultSet.getString(2)+
                "  score: "+resultSet.getString(3));
            }
            System.out.println("-----------------------------------------------------");
            pre.setInt(1,60);
            ResultSet resultSet1 = pre.executeQuery();
            System.out.println("60分以上:");
            while(resultSet1.next()){
                System.out.println("stu_id: "+resultSet1.getString(1)+
                        "  course_id: "+resultSet1.getString(2)+
                        "  score: "+resultSet1.getString(3));
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            try {
                if(pre != null) {
                    pre.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

插入数据:

public void insertScore(){
        //无参的SQL语句
        String insertSql = "insert into score values(?,?,?)";
        PreparedStatement pre = null;
        try {
            //讲无参的SQL语句提交给MySQL
            pre = connection.prepareStatement(insertSql);
            //给无参数的SQL语句提交参数
            pre.setInt(1,10);
            pre.setInt(2,11);
            pre.setInt(3,61);
            pre.executeUpdate();
            pre.setInt(1,22);
            pre.setInt(2,23);
            pre.setInt(3,59);
            pre.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            try {
                if(pre != null) {
                    pre.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

删除数据:

public void deleteScore(){
        String deleteSql = "delete from score where score = ?";
        PreparedStatement pre = null;
        try {
            pre = connection.prepareStatement(deleteSql);
            pre.setInt(1,100);
            pre.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            try {
                if(pre != null) {
                    pre.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

修改数据:

public void updateScore(){
        String updateSql = "update score set score = 85 where stu_id = ?";
        PreparedStatement pre = null;
        try {
            pre = connection.prepareStatement(updateSql);
            pre.setInt(1,3);
            pre.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            try {
                if(pre != null) {
                    pre.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

什么是SQL注入异常
SQL注入异常(SQL Injection)就是利用非法的SQL拼接,从而达到入侵数据库的目的。它的产生主要是由于程序对用户输入的数据没有进行严格的过滤,导致非法的数据库SQL语句的执行。SQL Injection具有很大的危害,攻击者可以利用它来读取、修改或者删除数据库内的数据,获取数据库中的用户名、密码等隐私信息,甚至可以获取数据库管理员的权限。一般的防火墙也很难防范SQL Injection,但是如果我们在操作数据库时,使用PreparedStatement对象来操作的话,就能够有效的防范SQL Injection

通过JDBC来操作事务

1、开启事务
在cmd中,我们使用"set autocommit = 0"来开启事务,而在Java中我们使用的是connection.setAutoCommit(false)来开启事务

2、设置隔离级别
在MySQL中一共有4中隔离级别:Read Uncommitted、Read Committe、Repeateble Read、Serializable。在cmd中,我们使用"set session transaction isolation level SERIALIZABLE"来将隔离级别设置为序列化,而在Java中我们使用的是connection.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE)

public void createConnection(){
        try {
            Class.forName(jdbcDriver);
            connection = DriverManager.getConnection(url,userName,password);
            if(!connection.isClosed()){
                System.out.println("连接建立成功");
                connection.setAutoCommit(false);//开启事务
                connection.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);//将隔离级别设置为序列化
            }else{
                System.out.println("连接建立失败");
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

3、回滚
在cmd中,我们使用rollback;在Java中,我们使用 connection.commit();

public void rollbackTest(){
        System.out.println("对回滚方法的测试:");
        System.out.println("初始数据:");
        selectScore();
        System.out.println("----------------------------------");
        insertScore();
        System.out.println("插入数据,但此时并未回滚:");
        selectScore();
        System.out.println("----------------------------------");
        try {
            connection.rollback();
            System.out.println("回滚之后:");
            selectScore();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

4、设置保存点
cmd:SAVEPOINT point1
Java:Savepiont point1 = connection.setSavepoint()

5、退回到保存点
cmd:ROLLBACK TO point1
Java:connection.rollback(point1)

/**
     * 设置保存点和退回到保存点测试方法
     */
    public void savePointTest(){
        System.out.println("初始数据:");
        selectScore();
        System.out.println("---------------------------------");
        try {
            System.out.println("第一次插入数据(在此处设置保存点point1):");
            insertScore();
            Savepoint point1 = connection.setSavepoint();
            selectScore();
            System.out.println("---------------------------------");
            System.out.println("第二次插入数据(未设置保存点):");
            insertScore1();
            selectScore();
            System.out.println("----------------------------------");
            System.out.println("此时回退到保存点point1,发现第二次插入的数据并未保存:");
            connection.rollback(point1);
            selectScore();
        } catch (SQLException e) {
            e.printStackTrace();
        }

    }

连接池介绍

工作原理
数据库连接池的基本思想就是给数据库建立一个“缓冲池”,解决了资源重复利用的问题。当用户第一次获取链接时,会先请求一定数量的连接放入连接池中(并且会记录每个连接的未使用时间),然后再将连接池中的连接给那些发出请求的用户。当连接池中的初始连接用完后,连接池就会先判断所创建的连接数量是否大于最大连接数,如果此时已经等于了最大连接数,那么就会等待那些已经建立好连接的用户使用完连接以后再分配给新发出请求的用户。也就是说,连接池中必须有空闲的连接时,新发出请求的用户才能进行连接。而当目前的连接数小于最大连接数时,则可以继续创建连接给那些新发出请求的用户,创建新连接的个数即为增长因子。

连接池的使用流程
1、导入依赖 c3p0与log4j,c3p0内部打印日志时会使用到log4j
2、参数配置,在c3p0内部借助了JDBC的相关操作
3、获取连接
4、操作MySQL数据库
5、关闭连接

连接池的关闭
在连接池中,我们无法像使用JDBC操作数据库时那样,直接通过close方法来关闭连接了。在使用通过连接池获取到的连接时,调用close方法只是将此连接又还给了连接池,并没有真正的关闭连接。可以通过关闭连接池的方法来真正的关闭连接

重要参数
initialSize:初始化连接数目(默认值3)
maxPoolSize:连接池中拥有的最大连接数(默认值15)
minPoolSize:连接池中保持的最小连接数(默认值3)
acquireIncrement:增长因子,连接池在无空闲连接时,一次性创建的新连接的数量(默认值3)
maxIdleTIme:连接的最大空闲时间,如果一个连接未被使用的时间超过了最大空闲时间,则会断开这个连接。

关于连接池操作的简单代码演示:

private final String url = "jdbc:mysql://127.0.0.1:3306/school?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai";
    private final String userName = "root";
    private final String password = "123456";
    private final String jdbcDriver = "com.mysql.jdbc.Driver";
    private final int initSize = 5;//初始连接数量
    private final int maxSize = 10;//最大连接数量
    private final int minSize = 2;//最小连接数量
    private final int acq = 2;//增长因子
    private final int idle = 60;//单位秒  空闲时间
    //c3p0连接池的数据对象
    private final ComboPooledDataSource dataSource = new ComboPooledDataSource();

    /**
     * 参数配置
     */
    public PoolService(){
        try {
            dataSource.setDriverClass(jdbcDriver);
            dataSource.setJdbcUrl(url);
            dataSource.setPassword(password);
            dataSource.setUser(userName);
            dataSource.setInitialPoolSize(initSize);
            dataSource.setMaxPoolSize(maxSize);
            dataSource.setMinPoolSize(minSize);
            dataSource.setAcquireIncrement(acq);
            dataSource.setMaxIdleTime(idle);
        } catch (PropertyVetoException e) {
            e.printStackTrace();
        }
    }

    /**
     * 给用户调用的获取连接的接口
     * @return
     */
    public Connection getConnection(){
        Connection connection = null;
        try {
            connection = dataSource.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return connection;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值