栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JDBC详细总结

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JDBC详细总结

目录

JDBC基本概念

快速入门

对JDBC各个接口和类的详解

 注册驱动

 获取数据库的连接对象

 获取执行sql语句的对象

 执行sql

 简易过程图

JDBC基础练习

 接收返回结果

 抽取工具类

 综合案例:实现登录

 SQL注入问题

解决SQL注入问题

 JDBC管理事务

 数据库连接池

引入原因:

 数据库连接池概念:

引入数据库连接池的好处:

实现:

获取连接:

归还连接:

数据库连接池实现

C3P0:

 C3P0的基本使用

 Druid:

 Druid基本使用

 Druid工具类

 JDBCTemplate

引入

步骤


JDBC基本概念

基本概念:Java Database Connectivity , Java数据库连接,Java语言操作数据库。

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

数据库驱动:各个厂商写的不同的接口的实现类又称数据库驱动。

 

快速入门

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;

public class JdbcTest01 {
    public static void main(String[] args) throws Exception {
        //导入驱动jar包
        //注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        //获取数据库的连接对象
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3307/db2","root","root");
        //定义sql语句
        String sql = "update account set balance = 500 where id = 1";
        //获取sql执行的对象
        Statement statement = connection.createStatement();
        //执行sql
        int count = statement.executeUpdate(sql);//返回执行sql语句后影响了几行数据
        System.out.println(count);
        //释放资源
        statement.close();
        connection.close();

    }
}

 1.导入MYSQL的驱动jar包:即MYSQL厂商的JDBC实现类。将mysql-connector-java-5.1.37-bin.jar导入工程中。

步骤:导入驱动jar包-->创建libs文件夹(方便管理)-->将其复制到文件夹-->右键add as library(将jar包加入到工作空间中)

2.注册驱动

3.获取数据库的连接对象

4.定义sql语句

5.获取执行sql语句的对象

6.执行sql,接收返回结果

7.处理结果

8.释放资源

对JDBC各个接口和类的详解

 注册驱动

导入jar包之后,我们如何让项目连接到mysql,然后写sql语句操作数据库呢?

   Class.forName("com.mysql.jdbc.Driver");

让我们先来看看这句代码是什么意思呢?

首先来了解一下Driver接口,查查API文档看看:

Driver是一个需要实现的接口,MYSQL厂商提供的Driver类实现了该接口。

该接口功能:每个Driver类会加载它可以找得到的驱动程序,然后让每个驱动程序尽可能连接到目标。

 还记得反射吗?如果忘啦,请看看这篇反射

MYSQL厂商提供的jar包中包含了一个与数据库连接的类——com.mysql.jdbc.Driver即驱动,我们通过反射技术Class.forName("全类名")来将字节码文件加载到内存中,类中有通过DriverManager实现注册驱动的方法,这些内容被写在静态代码块,随着类加载被执行。

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    //
    // Register ourselves with the DriverManager
    //
    static {
        try {
            //在加载时,就将自身注册到 DriverManager 中
            java.sql.DriverManager.registerDriver(new Driver());
        } catch (SQLException E) {
            throw new RuntimeException("Can't register driver!");
        }
    }
DriverManager中有一个注册驱动的方法,接下来DriverManager就可以进行一系列的管理。

 注册驱动:告诉程序该使用哪一个驱动jar包。

注意事项:在mysql5之后,提供的jar包里有自动注册驱动的services文件。

 获取数据库的连接对象
        //获取数据库的连接对象
        Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3307/db2","root","root");

我们来看看API文档是如何说明的:

 DriverManager是sun公司提供的一个管理JDBC驱动的类。

 DriverManager类中有一个静态方法getConnection用来建立到给定数据库URL的连接,通过类名.静态方法就可执行该方法。

 getConnection方法的参数含义如API文档中所示,该方法会返回一个Connection对象。

url:  mysql写法:jdbc:mysql://ip地址(域名):端口号/数据库名称

注意:如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为

jdbc:mysql:///数据库名称

 获取执行sql语句的对象
//获取sql执行的对象
        Statement statement = connection.createStatement();

查看API文档了解Connection对象

 Connection是一个sun公司的提供给我们的接口。

Connection中有一个静态方法createStatement()方法创建一个Statement对象来发送sql语句

 

Connection:数据库连接对象

功能:

1.获取执行sql的对象

2.管理事务

 执行sql
        //执行sql
        int count = statement.executeUpdate(sql);//返回执行sql语句后影响了几行数据

老样子,查看API文档:

 

 

 通过statement对象我们可以执行sql语句,现在就去你的数据库看看,sql语句是否被成功执行了。

 简易过程图

JDBC基础练习

要求1:在account表中添加一条数据(更新操作)


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

public class JdbcTest02 {
    public static void main(String[] args) {
        Connection connection = null;
        Statement statement = null;
        try {
            //注册驱动
            Class.forName("com.mysql.jdbc.Driver");
            //获取连接对象
            String url = "jdbc:mysql://localhost:3307/db2";
            connection = DriverManager.getConnection(url,"root","root");
            //编写sql语句
            String sql = "insert into account (id,name,balance) values (4,'赵四','10000')";
            //获取执行sql语句的对象
            statement = connection.createStatement();
            //执行sql语句
            int count = statement.executeUpdate(sql);
            if(count > 0){
                System.out.println("添加数据成功!");
            }
            else{
                System.out.println("添加数据失败!");
            }
        }
        catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        catch (SQLException e) {
            e.printStackTrace();
        }
        finally {
            //为了避免空指针异常,我们加上控制语句
            if(statement != null)
            {
                try {
                    statement.close();
                }
                catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(connection != null)
            {
                try {
                    connection.close();
                }
                catch (SQLException e) {
                    e.printStackTrace();
                }
            }

        }
    }
}

 接收返回结果

ResultSet  :结果集对象,封装查询结果,如何将结果展现出来呢?

next() :将游标向下移动一行,初始的时候游标在表头行,无法取数据,用该方法将游标向下移动一行。我们已经获取到行了,如何才能获取每一列的信息呢?

getXxx():获取数据,其中Xxx代表不同的类型,取决于要取的列的数据类型。

补充:statement对象中还有个方法为executeQuery()用来执行查询语句。

参数:

当参数是int类型的时候表示的是列的编号,编号从1开始。

当参数是String类型的时候表示的是列的名字。

让我们来看看API文档

 

 抽取工具类

目的:简化书写

分析:
1.抽取注册驱动

2.抽取一个方法获取连接对象:为了保证工具类的通用性,我们可以编写配置文件,读取配置文件里的参数,读取一次即可,代码就可以做到不改动,只用改动配置文件。

3.抽取一个方法释放资源

import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.Properties;

public class JdbcUtils {
    //只有提升它们的作用域,获取连接的方法才能使用
    private static String url;
    private static String user;
    private static String password;
    private static String driver;
  static {
  
      try {
          //读取资源文件,获取值
          //创建properties集合类
          Properties pro = new Properties();
          //为了更具有通用性,我们采用获取src路径下文件的方式ClassLoader类加载器,可以获取src下的文件
          ClassLoader classLoader = JdbcUtils.class.getClassLoader();
          URL res = classLoader.getResource("utils.properties");//获取到同一资源定位符
          String path = res.getPath();//获取它的字符串路径
          System.out.println(path);
          pro.load(new FileReader(path));
      }
      catch (Exception e) {
          e.printStackTrace();
      }
    }
    //执行连接的方法
    public static Connection getConnection() throws SQLException {
      return DriverManager.getConnection(url,user,password);
    }
    //释放资源的方法
    public static void closeRes(ResultSet resultSet, Statement statement, Connection connection){
        if(resultSet != null)
        {
            try {
                resultSet.close();
            }
            catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(statement != null)
        {
            try {
                statement.close();
            }
            catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(connection != null)
        {
            try {
                connection.close();
            }
            catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    public static void close(Statement statement,Connection connection){
        closeRes(null,statement,connection);
    }
}

 综合案例:实现登录
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;

public class login {
    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        System.out.println("用户名:");
        String username = scanner.next();
        System.out.println("密码:");
        String password = scanner.next();
        boolean result  = new login().loginMethod(username, password);
        if(result) {
            System.out.println("登录成功");
        }
        else{
            System.out.println("用户名或密码错误!");
        }

    }

    public boolean loginMethod(String name, String password) {
        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;
        try {
            connection = JdbcUtil.connection();
            String sql = "select * from user where name = '" + name + "' and password = '" + password + "'";
            statement = connection.createStatement();
            resultSet = statement.executeQuery(sql);
            return resultSet.next();

        }
        catch (SQLException e) {
            e.printStackTrace();
        }
        finally {
            JdbcUtil.closeResultSet(connection,statement,resultSet);
        }
    return false;
    }

}

import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.sql.*;
import java.util.Properties;


public class JdbcUtil {
    private static String url;
    private static String user;
    private static String password;
    private static String driver;
    
    static{
        //读取资源文件,获取值。
        Properties pro = new Properties();
        //加载文件进内存
        //获取src路径下的文件的方式----->ClassLoader 类加载器
        ClassLoader classLoader = JdbcUtil.class.getClassLoader();
        URL resource =classLoader.getResource("utils.properties");
        String path = resource.getPath();
        try {
            pro.load(new FileReader(path));
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        //3.获取数值,赋值。
        url = pro.getProperty("url");
        user = pro.getProperty("user");
        password = pro.getProperty("password");
        driver = pro.getProperty("driver");
//getProperty中一定要记得加上分号,否则默认为null,则无法实现注册驱动!!!
        try {
            //注册驱动
            Class.forName(driver);
        }
        catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
    public static Connection connection() throws SQLException {
        return DriverManager.getConnection(url,user,password);
    }

    
    public static void close(Connection connection, Statement statement) {
        if (statement != null) {
            try {
                statement.close();
            }
            catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if (connection != null) {
            try {
                connection.close();
            }
            catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    public static void closeResultSet(Connection connection, Statement statement,ResultSet resultSet) {
        if(resultSet != null) {
            try {
                resultSet.close();
            }
            catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (statement != null) {
            try {
                statement.close();
            }
            catch (SQLException e) {
                e.printStackTrace();
            }
        }

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

}

 SQL注入问题

 引入:在上面登录案例上,如果在拼接sql时,有一些sql的特别的关键字参与字符串的拼接,会造成非常严重的安全问题。

解决sql注入问题:使用PreparedStatement对象来解决

查看API文档看看:

 预编译的SQL:参数使用?作为占位符

使用变化:

1.定义sql:使用?作为占位符

2.获取执行sql语句的对象:通过 PreparedStatement Connection.prepareStatement(String sql)方法

3.给占位符赋值:利用PreparedStatement中的setXxx(参数1,参数2)

注:参数1:?的位置编号,从1开始

参数2: ?的值

4.执行sql时不需要传参数了,第二步已经传过了。

查看API文档看看 :

相比connection对象中的createStatement,这里相对应的是prepareStatement(String sql)方法。

 

 PreparedStatement对象创建好之后,利用该对象中的setXxx(参数1,参数2)赋值

 

解决SQL注入问题

将上面登陆代码稍微修改一下......

记得再写一个重载的preparedStatement释放资源的方法哦

 try {
            connection = JdbcUtil.connection();
            String sql = "select * from user where name = ? and password = ?";
            preparedsta = connection.prepareStatement(sql);
            preparedsta.setString(1,name);
            preparedsta.setString(2,password);
            resultSet = preparedsta.executeQuery();
            return resultSet.next();

        }

 JDBC管理事务

使用Connection对象来管理事务

开启事务:void setAutoCommit(boolean autoCommit):调用该方法设置参数为false,即开启事务。

提交事务:commit()

回滚事务:rollback()

 数据库连接池

引入原因:

按照我们上面编写的代码,未来使用在web项目中时,每一次用户的web请求都要建立一次连接,连接很耗时,频繁进行数据库的连接,必定会占用大量资源,造成网页响应速度很慢,因此我们引入了连接池概念。

 

 数据库连接池概念:

它其实就是一个存放数据库连接的的容器(集合)。当系统初始化好之后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完后,会将连接对象归还给容器。


引入数据库连接池的好处:

1.节约了系统的资源

2.用户访问高效

实现:

获取连接:

sun公司提供了一个接口DataSource,它的实现由数据库厂商提供。

查看API文档

 DataSource接口中的getConnection方法可以获取连接

 

归还连接:

 如果连接对象connection是从连接池中获取的,那么调用Connection.close()方法,则不会再关闭连接了,而是归还连接。

数据库连接池实现

它们由厂商实现,都实现了dataSource接口。

1.C3P0:数据库连接池技术

2.Druid:数据库连接池,由阿里提供

C3P0:

使用步骤:

1.由于连接池的实现是由各大厂商实现的,所以我们想要使用,就要先导入相应的jar包,即

c3p0-0.9.5.2.jar和mchange-commons-java-0.2.12.jar,不要忘记导入数据库连接包。

2.为了维护更加方便,我们用定义配置文件的方式,记得DriverManager.getConnection(参数)吗?这里相当于我们之前用配置文件获取该方法的参数值的方式。

注意:

这里的配置文件命名必须以c3p0.properties或者c3p0-config.xml,将来去使用的时候,会自己去寻找这个文件

路径默认在类路径(src)里,可以直接将文件直接复制到src下。

3.创建数据库连接池对象ComboPooledDataSource,ComboPooledDataSource 是c3p0封装了jdbc 对DataSource接口的实现。

4.获取连接:getConnection

 你需要至少能读懂xml文件...


  
  
  	
    com.mysql.jdbc.Driver
    jdbc:mysql://localhost:3307/db2
    root
    root
    
    
    
    5
    
    10
    
    3000
  

 C3P0的基本使用
import com.mchange.v2.c3p0.ComboPooledDataSource;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

public class C3p0Demo1 {
    public static void main(String[] args) throws SQLException {
        //创建数据库连接池对象,父类引用指向子类对象
        //没有参数使用默认连接:DataSource ds = new ComboPooledDataSource();
        DataSource ds = new ComboPooledDataSource("otherc3p0");
        //ComboPooledDataSource 是c3p0封装了jdbc 对DataSource接口的实现。
        //获取连接对象
        Connection connection = ds.getConnection();
        System.out.println(connection);
    }
}

 注意:

1.只有两个用户请求完全同时来(在多少毫秒内同时点击),才会一起使用连接池里的连接对象。

2.ComboPooledDataSource()没有参数的时候,用默认连接池,指定参数的时候,使用指定连接池。

 Druid:

使用步骤:

1.导入jar包 druid-1.0.9.jar

2.定义配置文件。

注意:

配置文件是properties形式的

配置文件可以叫任意名称,可以放在任意目录下,但是需要手动加入路径。

获取数据库连接池对象:通过工厂类DruiddataSourceFactory来获取

3.获取连接:getConnection

 Druid基本使用
import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties;

public class DruidDemo1 {
    public static void main(String[] args) throws Exception {
        //加载配置文件
        Properties pro = new Properties();
        InputStream is = DruidDemo1.class.getClassLoader().getResourceAsStream("druid.properties");
        pro.load(is);
        DataSource dataSource = DruidDataSourceFactory.createDataSource(pro);
        //获取连接
        Connection connection = dataSource.getConnection();
        System.out.println(connection);
    }
}

 Druid工具类

创建步骤:

1.定义一个工具类

2.提供静态代码块加载配置文件,初始化连接对象

3.提供方法:

*获取连接方法:通过数据库连接池获取连接

*释放资源

*获取连接池的方法(有的框架中,只需要连接池,不需要连接对象,它会自动调用连接对象。)

import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

public class JdbcUtilDruid {
    //定义成员变量DataSource
    private static DataSource ds;
    static{
        try {
            //加载配置文件
            Properties pro = new Properties();
            pro.load(JdbcUtilDruid.class.getClassLoader().getResourceAsStream("druid.properties"));
            //获取datasource
            ds = DruidDataSourceFactory.createDataSource(pro);
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
    //获取连接的方法
    public static Connection getConnection() throws SQLException {
        return ds.getConnection();
    }
    //获取连接池
    public static DataSource getDs(){
        return ds;
    }
    //归还资源
    public static void close(Statement statement ,Connection connection)
    {
        close(null,statement,connection);//简化
    }
    //重载方法
    public static void close(ResultSet resultSet ,Statement statement,Connection connection)
    {
        if(resultSet != null){
            try {
                resultSet.close();//归还资源
            }
            catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(statement != null){
            try {
                statement.close();//归还资源
            }
            catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if(connection != null){
            try {
                connection.close();//归还资源
            }
            catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

 JDBCTemplate

引入

当我们创建连接后,编写sql语句进行查询时,处理结果时非常复杂,为了简化我们的书写,Spring框架提供了对JDBC的简单封装,提供了一个JDBCTemplate对象简化JDBC的开发。

步骤

1.导入相关jar包

2.创建JdbcTemplate对象,依赖于数据源DataSource

JdbcTemplate template = new JdbcTemplate(ds);

3.调用JdbcTemplate的方法来完成CRUD的操作

count update(参数1,参数2): 执行DML语句。增删改语句,参数1需要传递sql语句,参数2传递?对应的值,返回影响行数。

Map<>   queryForMap(参数1,参数2): 查询结果将结果集封装为map集合,返回map集合,参数1需要传递sql语句,参数2传递?对应的值,这个方法查询的结果集只能是一个,将列名作为key将值作为value。

List>   queryForList(参数1) : 查询结果将结果集封装为list集合。参数1为sql语句。将每一条记录封装为一个Map集合,然后将Map集合装载到List集合中。

query() : 查询结果,将结果封装为JavaBean对象

queryForObject :查询结果,将结果封装为对象

import druid.JdbcUtilDruid;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;

public class Template01 {
    DataSource dataSource;

    {
        dataSource = JdbcUtilDruid.getDs();
        //创建JdbcTemplate对象
        JdbcTemplate template = new JdbcTemplate(dataSource);
        String sql = "update account set balance = 1024 where id = ?";
        template.update(sql,3);
        //不需要申请连接,也不需要释放资源,内部已经封装好了。
    }
}

 如有错误,请指正~

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/459769.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号