JDBC总结说明

JDBC

JDBC本质是一套接口(interface)

接口都有调用者和实现者,面向接口调用,面向接口实现类;

面向接口编程,本质面向抽象编程,解耦降低耦合度,实现高可扩展性。(多态);

java提供JDBC接口,数据库厂商根据接口进行实现(数据库厂家官网下载),提供jar包驱动(实现类),引用驱动进行数据库连接访问。

利用反射实现JDBC连接

public class javaPro{
ResourceBundle  r = ResourceBundle.get ("popertites文件");
String value  = r.getString(“key”);
Class c = Class.forName(value);
//通过反射,创建JDBC对象
JDBC jdbc = c.newInstance();
//实现连接
jdbc.getConnection();
}

JDBC编程6步

第一步:注册驱动(作用:告诉java程序,即将要连接的是那个品牌的数据库)

第二步:获取连接(表示JVM的进程和数据库进程之间的通道打开了,属于进程之间的通信,使用完之后一定要关闭)

第三步:获取数据库操作对象(专门执行SQL的对象)

第四步:执行SQL语句(DQL、DML)

第五步:处理查询结果(只有第四步执行的是SELECT语句的时候,才会有第五步的处理结果)

第六步:释放资源

public class JDBCTest01 {
    public static void main(String[] args) {
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;
        try {
            //1.注册驱动
            DriverManager.registerDriver(new com.mysql.jdbc.Driver());
            //2.建立连接
            //统一资源定位符
            //通信协议 jdbc:mysql:
            //IP端口 localhost:3306
            //资源名 sys-具体数据库实例名称
            String url = "jdbc:mysql://localhost:3306/sys";
            String user = "root";
            String password = "123456";
            conn = DriverManager.getConnection(url, user, password);
            //测试验证数据库连接对象
            //System.out.println(conn);
            //3.获取数据库操作对象(执行SQL语句)
            stmt = conn.createStatement();
            //4.编写执行sql,jdbc语句不需要写分号
            String sql = "select * from sys_user";
            //执行dml语句,返回值是影响数据库条数
            //in count = stmt.executeUpdate(sql);
            //执行查询语句
            stmt.executeQuery(sql);
            rs = stmt.getResultSet();
            //5.处理结果
            while(rs.next()){
                .....
            }

        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            //6.释放连接
            //为了来保证资源一定是释放,在finally中关闭资源
            //并且遵循从小到大依次关闭
            //分别对其try...catch
            try {
                if (rs != null) {
                    rs.close();
                }
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }

            try {
                if (stmt != null) {
                    stmt.close();
                }
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }

            try {
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }

    }
}
//类加载的方式注册驱动,可使用xxx.properties文件参数获取
try {
    Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
    throw new RuntimeException(e);
}

statement存在SQL注入风险

使用preparedStatement,预编译数据库操作对象。解决用户提供的参数包含SQL关键字,但这些关键字为参与SQL编译,不会起作用。

sql语句中的变量使用 ? -占位符。

ps = conn.prepareStatement(sql);
//给占位符赋值参数,jdbc索引下表从1开始,几个占位赋值几个
ps.setString(1,参数)
ps.setString(2,参数)
//执行SQL
ps.executeQuery();

Statement与PreparedStatement比较

1、Statement会导致SQL注入不安全,PreparedStatement不会。

2、Statement编译一次执行一次,PreparedStatement执行效率库快,编译一次可以执行N次。

3、PreparedStatement在编译阶段会进行类型检查。preparedStatement.setXXX(1,参数)方法会对参数类型检查。

综上,大部分情况使用PreparedStatement

业务方面要求支持SQL注入、SQL语句拼接时才使用Statement。

JDBC中的默认事物是自动提交的,只要执行任意一条DML语句,就会提交;

但是实际开发过程中需要保持事物的一致性与原子性,需修改自动提交机制。

//开启手动提交事物
connections.setAutoCommit(false);
//事物提交
connections.commit();
//事物回滚
connections,rollback();

简化编程可以写JDBC工具类

import java.sql.*;
import java.util.ResourceBundle;

public class DBUtil {
    /**
     * 工具类中的构造方法建议私有
     * 工具类的方法都是静态方法,不需要进行实例化,直接采用类名调用
     */
    private DBUtil() {
    }

    ;

    //静态代码块,类加载时只执行一次。
    static {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 建立数据库链接
     *
     * @param porperties JDBC配置文件
     * @return
     * @throws SQLException
     */
    public static Connection getConnection(String porperties) throws SQLException {
        ResourceBundle resourceBundle = ResourceBundle.getBundle(porperties);
        String url = resourceBundle.getString("url");
        String username = resourceBundle.getString("username");
        String password = resourceBundle.getString("password");
        return DriverManager.getConnection("porperties", username, password);
    }

    /**
     * 关闭资源
     * 程序执行到这已经最后处理,上抛资源无人处理异常
     *
     * @param conn 连接对象
     * @param ps   数据库操作对象
     * @param rs   结果集
     */
    public static void close(Connection conn, PreparedStatement ps, ResultSet rs) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
        if (ps != null) {
            try {
                ps.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

悲观锁和乐观锁

悲观锁:行级锁为悲观锁,事物必须排队,数据锁住了,不允许并发(select … for update)。

乐观锁:允许并发,事务不需要排队,提交事务前,根据版本号确认是否有事务进行更新,若当前获取的版本号不是最新的版本号则回滚事物,反之提交事物。

额外注释

ResourceBundle 用来读取poperties文件

popertites文件内容

key=value

ResourceBundle 使用方法

ResourceBundle r = ResourceBundle.get ("popertites文件名");

String value = r.getString(“key”);

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值