Java学习笔记之JDBC

JDBC


穷且益坚 不坠青云之志

一、概念

1. 简介

  • JDBC:Java DataBase Connectivity,java语言操作数据库
  • JDBC本质:官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口。各个数据库厂商去实现这套接口,提供数据库驱动jar包。我们可以使用这套接口(JDBC)编程,真正执行代码时驱动jar包中的实现类

二、入门

1. 步骤

  • 1)导入jar包
    • 复制驱动到项目的libs目录下
    • 右键–Add As Library
  • 2)注册驱动
  • 3)获取数据库连接对象 Connection
  • 4)定义sql语句
  • 5)获取执行sql语句的对象 Statement
  • 6)执行sql,接收返回结果
  • 7)处理结果
  • 8)释放资源

2. 代码

//1.导入jar包
//2.注册驱动
Class.forName("com.mysql.cj.jdbc.Driver");

//3.获取数据库连接对象
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/girls?serverTimezone = GMT", "root", "root");

//4.定义sql语句
String sql = "update admin set password = 7777 where id = 2";

//5.获取执行sql的对象
Statement statement = conn.createStatement();
//6.执行sql
int count = statement.executeUpdate(sql);
//7.处理结果
System.out.println(count);

//8.释放资源
statement.close();
conn.close();

三、详解

1. 各个对象

  • 1)DriverManager:驱动管理对象
  • 2)Connection:数据库连接对象
  • 3)Statement:执行sql的对象
  • 4)ResultSet:结果集对象
  • 5)PreparedStatement:

2. 详解

2.1 DriverManager

① 功能:

  • 1)注册驱动:告诉程序应该使用哪个数据库驱动jar

    • 方法:static void registerDriver(Driver driver),注册给定的程序驱动

    • 而写代码时却用的时:Class.forName("com.mysql.cj.jdbc.Driver");这是为什么呢?

    • 通过查看源码发现:在com.mysql.cj.jdbc.Driver类中存在静态代码块

    • static {
          try {
              java.sql.DriverManager.registerDriver(new Driver());
          } catch (SQLException E) {
              throw new RuntimeException("Can't register driver!");
          }
      }
      
    • 静态代码块在加载进内存时自动执行

  • 2)获取数据库连接

    • 方法:static Connection getConnection(...)
      • url:指定连接的路径:
        • jdbc:mysql://ip地址:端口/数据库名称
        • 在最新驱动中还需要添加:?serverTimezone = GMT
      • user:用户名
      • password:密码
2.2 Connection

① 功能

  • 1)获取执行sql的对象
    • Statement createStatement(String sql)
    • PreparedStatement prepareStatement(String sql)
  • 2)管理事物
    • 开启事物:void setAutoCommit(boolean autoCommit):调用该方法设置参数为false,即开启事物
    • 提交事物:commit()
    • 回滚事物:rollback()
2.3 Statement

① 功能

  • 1)执行sql
    • boolean execute(String sql):可以执行任意的sql语句(了解)
    • int executeUpdate(String sql):执行DML、DDL语句
      • 返回值:影响的行数。可以通过影响的函数可以判断DML语句是否执行成功(>0)
    • ResultSet executeQuery(String sql):执行DQL语句
2.4 ResultSet

① 功能:封装结果集对象

  • boolean next():游标下移一行
  • getXxx(参数):获取数据
    • Xxx:Int、String…
    • 参数:
      • int:代表列的编号(从1开始)。如:getInt(1)
      • String:代表列的名称。如:getString("password")

② 正确使用

while (rs.next()) {
    String name = rs.getString(2);
    System.out.println(name);
}
2.5 PreparedStatement

① 简介

  • 1)SQL注入:在拼接sql时,有一些sql的特殊关键字参与字符串拼接,造成安全问题
  • 2)PreparedStatement:预编译的SQL:参数使用作为占位符
  • 3)PreparedStatement可以防止SQL注入
  • 4)PreparedStatement 是 Statement 的子类

② 使用步骤

  • 1)SQL语句:String sql = select * from where id = ?
  • 2)获取对象:PerparedStatement = conn.prepareStatement(sql)
  • 3)设置参数:setXxx(参数1, 参数2)
    • 参数1:?的位置编号(从1开始)
    • 参数2:?的值
  • 4)执行SQL:与Statement的使用方式一样(不需要在传递sql)

四、JDBCUtils

1. 分析

  • 封装注册驱动
  • 封装获取连接对象
  • 封装释放资源

2. 代码

/**
 * JDBC工具类
 */
public class JDBCUtils {
    private static String url;
    private static String user;
    private static String password;
    private static String driver;

    //读取配置文件
    static {
        try {
            Properties pro = new Properties();
            ClassLoader classLoader = JDBCUtils.class.getClassLoader();
            InputStream is = classLoader.getResourceAsStream("jdbc.properties");
            pro.load(is);

            url = pro.getProperty("url");
            user = pro.getProperty("user");
            password = pro.getProperty("password");
            driver = pro.getProperty("driver");

            Class.forName(driver);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }


    //获取连接对象
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url, user, password);
    }

    //释放资源
    public static void close(Statement stmt, Connection conn){
        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    //释放资源
    public static void close(ResultSet rs, Statement stmt, Connection conn){
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

五、事物

1. 简介

  • 1)事物:一个包含多个步骤业务的操作。如果这个步骤被事物管理,则这个步骤要么同时成功,要么同时失败
  • 2)操作:
    • 开启事物:void setAutoCommit(boolean autoCommit)
    • 提交事物:commit()
    • 回滚事物:rollback()
  • 3)使用Connection对象管理事物
  • 4)使用场景:在代码出现异常时,需要使执行完毕的代码回到未执行时。

2. 使用

try{
    conn = JDBCUtils.getConnection();
    //设置开启事物
    conn.setAutoCommit(false);
    
    //...代码
    
    //最后提交事物
    conn.commit();
}catch(Exeception e){
    //如果在代码执行过程中出现异常,应回滚事物
    try{
        if(conn != null){
            conn.rollback();
        }
    }catch(SQLExeception e1){
        e1.printStackTrace();
    }
}finally{
    //关闭资源
}

六、连接池

1. 简介

① 概念

  • 连接池就是一个容器(集合),存放数据库连接的容器
  • 当系统初始化后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取对象。用户访问完之后,会将连接对象归还给容器
  • 好处:节约系统资源、高效

② 实现

  • 标准接口:DataSource(javax.sql)
    • 获取连接:getConnection()
    • 归还连接:Connection.close()
  • 一般我们不去实现它,由数据库厂商来实现
    • C3P0:数据库连接池技术
    • Druid:数据库连接池技术(阿里巴巴提供)

2. C3P0

① 步骤

  • 1)导入jar包:
    • c3p0.far
    • mchange-commins-java.far
    • mysql驱动jar包
  • 2)定义配置文件:
    • 名称:c3p0.properties 或者 c3p0-config.xml
    • 路径:将文件放在src目录下
  • 3)创建数据库连接池对象:ComboPooledDataSource
  • 4)获取连接:getConnection

② 代码

 //1.创建数据库连接对象
DataSource ds = new ComboPooledDataSource();
//2.获取连接对象
Connection conn = ds.getConnection();

3. Druid

① 步骤

  • 1)导入jar包:druid-1.0.9.jar
  • 2)定义配置文件:
    • 是properties形式文件
    • 可以叫任意名称,可以放在任意目录下
  • 3)加载配置文件
  • 4)获取数据库连接池对象:通过工厂类获取:DruidDataSourceFactory.createDataSource(pro)
  • 5)获取连接:getConnection()

② 定义工具类

  • 定义类
  • 提供静态代码块,加载配置文件,初始化连接池对象
  • 提供方法:
    • 获取连接方法:通过数据库连接池获取连接
    • 释放资源
    • 获取连接池的方法

③ 代码

@Test
public void testDruid() throws Exception {
    //1.导入jar包
    //2.定义配置文件

    //3.加载配置文件
    Properties properties = new Properties();
    InputStream is = Test01_Druid.class.getClassLoader().getResourceAsStream("druid.properties");
    properties.load(is);

    //4.获取连接池对象
    //在spring中发现,由spring创建的是DruidDataSource对象,故,DataSource是接口。
    //DruidDataSource的父类集成了DataSource接口
    DataSource ds = DruidDataSourceFactory.createDataSource(properties);

    //5.获取连接
    Connection connection = ds.getConnection();
    System.out.println(connection);
}

七、Spring JDBC:Template

1. 简介

  • Spring框架对JDBC的简单封装。提供类一个JDBCTemplate对象简化JDBC的开发
  • 使用Template时需要使用数据库连接池技术

2. 步骤

  • 1)导入jar包(5个)
  • 2)创建JDBCTemplate对象。依赖与数据源DataSource
    • 如:JdbcTemplate template = new JdbcTemplate(ds)
  • 3)调用JDBCTemplate的方法来完成CRUD的操作
    • update():执行DML语句(增删改)。
    • queryForMap():查询结果,并封装为map集合:返回结果只能是一个
    • quertForList():
    • query():查询结果,封装为JavaBean
      • 参数1:sql语句
      • 参数2:new BeanPropertyRowMapper<Admin>(Admin.class)
    • queryForObject:查询结果,封装为对象

八、读写Blob数据

1. 简介

① blob类型

  • tinyBlob:255
  • blob:65k
  • mediumBlob:16m
  • longBlob:4g

② 报错:too large

  • 在mysql安装目录下,my.ini文件添加max_allow_package=16M,并重启服务

2. 实现

① DML

 /**
 * 插入和修改操作一样
 * 需要先读取文件流
 * @throws Exception
 */
@Test
public void testInsert() throws Exception {
    //1.获取连接
    Connection conn = JDBCUtils.getConnection();
	//2.创建sql语句
    String sql = "update beauty set photo = ? where id = ?";
	//3.创建执行sql对象
    PreparedStatement ps = conn.prepareStatement(sql);
	//4.获取文件流
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("9.jpg")));
    //5.设置参数
    ps.setBlob(1, bis);
    ps.setInt(2,1);

    ps.executeUpdate();

    JDBCUtils.close(ps, conn);
}

② DQL

@Test
public void testRead() throws Exception {
    Connection conn = JDBCUtils.getConnection();

    String sql = "select photo from beauty where id = ?";

    PreparedStatement ps = conn.prepareStatement(sql);
    ps.setInt(1, 1);

    ResultSet rs = ps.executeQuery();
    if (rs.next()) {
        //            Blob blob = rs.getBlob(1);
        //将blob类型的字段下载下来,以文件的方式保存本地
        Blob photo = rs.getBlob("photo");
        InputStream is = photo.getBinaryStream();

        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File("09_query.jpg")));

        byte[] buffer = new byte[1024];
        int len;
        while ((len = is.read(buffer)) != -1) {
            bos.write(buffer, 0, len);
        }
        bos.flush();
    }
    JDBCUtils.close(rs, ps, conn);
}

getBlob(1);
//将blob类型的字段下载下来,以文件的方式保存本地
Blob photo = rs.getBlob(“photo”);
InputStream is = photo.getBinaryStream();

    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File("09_query.jpg")));

    byte[] buffer = new byte[1024];
    int len;
    while ((len = is.read(buffer)) != -1) {
        bos.write(buffer, 0, len);
    }
    bos.flush();
}
JDBCUtils.close(rs, ps, conn);

}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值