JDBC

jdbc - java database connectivity - java数据库连接

用java编写的程序来连接的数据库的技术.jdbc是sun公司制定的一套”规范”,里面提供了大量的接口.由不同的db厂商进行实现.

而这些实现类就是驱动.

jdbc是最原始的持久层[和db交互层]的技术,属于JavaEE十三种核心技术中的一种.后期学习的持久层框架都是对jdbc的封装.

为什么要有jdbc

如果没有jdbc

1
2
3
4
5
6
7
8
9
10
11
12
SqlServerDriver driver = new SqlServerDriver();//sqlserver

MysqlDriver driver = new MysqlDriver();//mysql

//java切换db比较麻烦 - 换一套连接db的代码.

//sun制定jdbc规范 - 连接db的规范

//java.sql.Driver[I],不同的db厂商都是要去实现这个接口的

//伪代码
Class.forName("驱动类的全限定名"); // 可以配置到文件中的.

优势

为java程序访问不同的db提供统一的方式.在切换db的时候,能够做到最少改动.

相关api

  1. java.sql.Driver[I] - 每个驱动程序类必须实现的接口. jdbc编程第一步就是需要加载驱动[jdbc规范4.x开始可以省略不写]

  2. java.sql.DriverManager[C] - 驱动管理类. 获取连接

    • static Connection getConnection(String url,String user,String password)

      1
      2
      3
      user : db用户名
      password: db密码
      url: 主协议:次协议://ip地址:端口号/db名称?key1=value1&key2=value2
  3. java.sql.Connection[I] - 一次会话/连接

    • Statement createStatement();
    • PreparedStatement prepareStatement(String sql);//预编译语句对象
    • CallableStatement prepareCall();// 调用存储过程.
  4. java.sql.Statement[I] - 负责将sql语句发送到db-server端

    • int executeUpdate(String sql);// 用于执行DML操作,insert,update,delete
    • ResultSet executeQuery(String sql);//用于执行DQL语句
  5. java.sql.ResultSet[I] - 结果集对象

    本质上仅仅是一个游标.默认指向第一行的上方.

    • boolean next();//1. 游标向下移动一行;2. 如果下一行没有行记录,则返回false
    • 取列值. String getString(int colINdex);//根据列的序号取值,第一列就是1
    • 取列值 - String getString(String colName);//根据列的名称(支持使用别名)

体验

查询 - 六大编程步骤

  1. 脚本

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    drop table jdbc_user;
    create table jdbc_user(
    id int(7) primary key auto_increment,
    username varchar(20) not null unique,
    password varchar(20),
    birthday date,
    power int(1) comment '0-管理员,1-普通用户'
    );
    insert into jdbc_user values(1,'admin','123','2021-01-01',0);
    insert into jdbc_user values(2,'tom','123','2021-01-01',1);
    insert into jdbc_user values(3,'蔡根花','123','2021-01-02',1);
  2. 实体类

    1
    2
    3
    4
    5
    6
    7
    public class User implements Serializable {
    private Integer id;
    private String username;
    private String password;
    private Date birthday;
    private Integer power;
    }
  3. 制定持久层的接口 - IUserDao.java

  4. 制定持久层的实现类 - UserDaoImpl.java

  5. 单元测试

Statement弊端

  1. 参数硬拼接到了sql语句中,比较麻烦的

  2. 容易造成SQL注入 - 非法的参数/sql硬拼接到了sql语句中.

  3. 缺点 - 通过语句对象每次发送sql到db-server端,都是需要对sql语句进行编译和解析的.但是业务中可能遇到同构的sql.

    同构的sql还是会多次编译和解析的,比较影响性能.

  4. 优点 - 一个statement对象可以用来多次发送不同的sql语句.

PreparedStatement[I]

预编译语句对象

提前将带有占位符号的sql发送到db-server进行解析,后面只要发送参数即可.适合同构的sql

缺点: 一个pst对象,只能编译一条sql语句.

批处理效率问题

addBatch(String sql);//向当前批处理中添加一条sql语句。
executeBatch();//执行批处理
clearBatch();//清空批处理

需要在url中添加rewriteBatchedStatements=true

JDBC事务

  • jdbc事务 - 由连接的db决定

  • jdbc事务 - 编程性事务 - 事务代码和应用程序代码耦合在一块儿的.

  • spring事务 - 声明式事务.事务代码(与业务无关的代码)和应用程序进行分离.

  • jdbc事务 - dml操作之后默认都是自动commit - executeUpdate

  • 代码示例的结构

    1
    2
    3
    4
    5
    6
    7
    try{
    conn.setAutoCommit(false);

    conn.commit();
    }catch(Exception e){
    conn.rollback();
    }

模板设计模式

针对DML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Connection conn = null;
PreparedStatement pst = null;
try {
conn = JdbcUtil.getConnection();

//特殊的地方 - 个性的地方
pst = conn.prepareStatement("delete from jdbc_user where id=?");
pst.setInt(1,id);

return pst.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally {
JdbcUtil.close(conn,pst);
}

ResultSetMetaData

结果集元数据