(2)JavaWeb学习之JDBC

JDBC的基本介绍

-概念:Java DataBase Connectivity Java 数据库连接, Java语言操作数据库。我们为什么要学习JDBC?因为我们前面学习的数据库是有许多的不同的,我们想操作一个数据库就要专门去学所对应的“方言”,十分麻烦。而学习了JDBC我们就可以用java去操作数据库,一招鲜,吃遍天!!

-本质:其实是官方(sun公司)定义的一套操作所有关系型数据库的规则,即接口。(定义了操作所有关系型数据库的规则)
【ps】:只提供了接口,具体的实现类并不由公司提供。

而各个数据库厂商去实现这套接口,提供数据库驱动jar包(即:包含这个版本数据库的JDBC接口的实现类)。

我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。

例如:定义一个Person接口(类比此处的JDBC接口),然后创建实现类Worker(类比这里的各个数据库厂商根据JDBC接口创建的实现类(将这些实现类封装为jar包,相当于数据库驱动)),我们只需要“Person p = new Worker()”创建实现类的对象,调用“p.eat()”,就可以调用实现类Worker复写Person接口的eat方法(类比我们创建各个数据库厂商提供的实现类的对象(从jar包获取),这样我们就可以调用这些实现类的方法,来操作数据库)在这里插入图片描述
  也就是:我们使用JDBC这个接口进行编程,而真正执行的代码是驱动jar包中的实现类!
  事实上我们的程序对jar包中实现类的使用在底层实现,我们只需要在java文件中导入jar包,按固定的流程去使用,既可以通过java操作数据库。注意流程

JDBC运作入门
步骤:

一. 导入驱动jar包 mysql-connector-java-5.1.37-bin.jar
驱动jar包下载地址
1)复制mysql-connector-java-5.1.37-bin.jar到项目的libs目录下
2)右键–>Add As Library (这一步将libs设置为项目级别的library类库,并添加到我们当前所使用的模块中。这样我们的模块才能使用libs文件夹中的jar包,才是真正的将jar包添加到我们的项目中)

二.注册驱动 (使程序知道我们使用的是哪一个版本的jar包)

三. 获取数据库连接对象 Connection
这个对象其实就是java本地代码与数据库的一个桥梁。

四. 定义sql
定义SQL语句后,我们将来通过一定的方式将SQL语句发送给数据库,数据库就会帮我们执行这些SQL语句,从而达到java代码操作数据库的目的

五. 获取执行sql语句的对象 Statement
第四步中我们定义了sql语句,我们接下来就要去用这个sql语句。则我们应该调用对象的方法来执行,但第三步我们获取的Connection对象并不能直接执行,我们需要获取一个执行sql语句的对象。

六. 执行sql,接受返回结果

七. 处理结果
至此其实我们已经达到了java操作数据库的目的了。但还有一步不能忘记。
八. 释放资源
具体代码实现:

public class JdbcDemo1
{
    public static void main(String[] args) throws Exception
    {
        //1. 导入驱动jar包(你连接什么数据库 你就导对应的包)
           /*分为两步:
             第一步:复制mysql-connector-java-8.0.19.jar到项目的libs的目录下(没有libs也行 直接复制到目录下 最好就创建一个libs方便管理)
             第二步:点击libs->add as library
             */
       //2.注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        
       //3.获取数据库连接对象
        Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1", "root", "root");//这里使用数据库db1
        //Connection con = DriverManager.getConnection("jdbc:mysql:///db1", "root", "root");//本机且数据库的端口是3306,那么可以省略一部分路径名
        
    //4.定义sql语句
        String sql = "update account set balance = 500 where id = 1";//注意SQL语句后不要加分号
        
        //5.获取执行sql的对象 Statement
        Statement sm = con.createStatement();
        
        //6.执行sql
        int count = sm.executeUpdate(sql);
        
       //7.处理结果
        System.out.println(count);
        
        //8.释放资源
        sm.close();//关闭SQL执行对象
        con.close();//关闭SQL的连接数据库对象
        /*
        结果:打印数据1,并且db1数据库的account表的数据发生变化
         */
    }
}
详解JDBC的各个对象

我们所导入的JDBC对象都是接口或类,但是真正执行的是我们导入的jar包中的实现类。我们编程中没有使用到导入的jar包的任何类(没有创建这些类的对象),但是我们编写的代码底层会使用jar包里面类的相关数据。

1.DriverManager:驱动管理对象

1. 注册驱动:告诉程序该使用哪一个数据库驱动jar包
DriverManager使用的注册驱动的方法:static void registerDriver(Driver driver):注册与给定的驱动程序 DriverManager 。 在这里插入图片描述
上文代码使用: Class.forName(“com.mysql.jdbc.Driver”);
我明明后续代码没有用到Driver这个类 为什么此处要引入Driver呢?->这个方法是将"com.mysql.jdbc.Driver"类的字节码文件加载进入内存。一当Driver类被加载进内存,其里面的静态代码块也会执行。 也就是说,当我引入了Driver这个类,就有一部分代码自动执行了。并不是没有用到。
在这里插入图片描述
在这里插入图片描述
观察代码可知:是DriverMnager在注册驱动
/*
为什么可以找到"com.mysql.jdbc.Driver"这个类?
因为我们导入了jar包,且jar包加入项目的类库,那么Class的forName方法就可以找到jar包,而jar包的com\mysql\jdbc文件夹下有一个Driver.class的文件。
那么Class类的forName()方法就可以获取这个Driver.class文件的Class对象,从而将这个Driver类加载进内存,执行里面的静态代码块,也就注册了这个jar包的驱动
*/
// 我们使用反射创建"com.mysql.jdbc.Driver"类的字节码文件Class对象,同时这个字节码文件对应的Driver类的代码也会加载进内存,这样静态代码块里面的代码也会执行,通过DriverManager的registerDriver方法注册驱动。
//registerDriver方法的参数driver - 将向 DriverManager 注册的新的 JDBC Driver
注意:mysql5之后的驱动jar包可以省略注册驱动的步骤。(jar包的META-INF文件的services文件夹里面有一个java.sql.Driver文件,它里面有“com.mysql.jdbc.Driver”文件,这样系统就会自动帮我们注册驱动。如果我们没有注册驱动,jar包会先读取java.sql.Driver文件并自动注册驱动)建议手动注册jar包的驱动。------------------------------------------------------------------------
2. 获取数据库连接:
* 方法:static Connection getConnection(String url, String user, String password)
* 参数:
* url:指定连接的路径
* 语法:jdbc:mysql://ip地址(域名):端口号/数据库名称
* 例子:jdbc:mysql://localhost:3306/db3
* 细节:如果连接的是本机mysql服务器,并且mysql服务默认端口是3306,则url可以简写为:jdbc:mysql:///数据库名称 (注意这里有三个斜杆)
* user:用户名
* password:密码

2.Connection:数据库连接对象

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

3.Statement:执行sql的对象

执行sql
1. boolean execute(String sql) :可以执行任意的sql
2. int executeUpdate(String sql) :执行DML(insert、update、delete)语句、DDL(create,alter、drop)语句(DDL语句用的比较少,我们一般都使用SQL语句执行DDL)
官方定义:executeUpdate(String sql) 执行给定 SQL 语句,该语句可能为 INSERT、UPDATE 或 DELETE 语句,或者不返回任何内容的 SQL 语句(如 SQL DDL 语句)。
* 返回值:影响的行数,可以通过这个影响的行数判断DML语句是否执行成功 返回值>0的则执行成功,反之,则失败。
3. ResultSet executeQuery(String sql) :执行DQL(select)语句

4.ResultSet:结果集对象,封装查询结果
5.PreparedStatement:执行sql的对象 是Statement的子类

抽取JDBC工具类 : JDBCUtils

作用: 简化了书写,不用总是去写重复的注册驱动啊 建立连接啊 释放资源。降低了代码的重复度。

分析:1. 注册驱动也抽取
2. 抽取一个方法获取连接对象
* 需求:不想传递参数(麻烦),还得保证工具类的通用性
* 解决:配置文件(也就是下图中的properties)
好处在于我们以后要修改参数的话在配置文件处改就好了,代码块的内容一点都不用改变
jdbc.properties
url=
user=
password=
3. 抽取一个方法释放资源

首先我们需要在src包下创建一个配置文件——jdbc.properties,将我们需要的信息写入这个文件,后期可以读取使用。(包括注册驱动以及连接数据库的相关信息)
在这里插入图片描述
下面展示一些 内联代码片

//-----------------------JDBCUtil类
package lkj.demo.jdbc;

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

/**
 * JDBC工具类
 */
public class JDBCUtil
{
    //外面先定义几个变量,用于接收从jdbc.properties文件读取的相关信息
    //变量定义为static,因为要在静态代码块中使用
    private static String url;
    private static String user;
    private static String password;
    private static String driver;
    /**
     * 文件的读取,只需要读取一次即可拿到这些值。使用静态代码块
     */
    static
    {
        //静态代码块的异常只能处理而不能抛出只有方法才能抛出异常
        try
        {
       **//1.先创建Properties对象**
            Properties p = new Properties();
            //获取src路径下的文件的方式--->ClassLoader 类加载器
            /*
            我们的目的是获取jdbc.properties文件的所在路径,这样就可以通过这个路径获取jdbc.properties文件的读取流
            再将读取流加载到Properties类中,就可以获取jdbc.properties文件中的信息
             */
            //这样,我们先通过当前类JDBCUtil的Class获取其类加载器
            ClassLoader classLoader = JDBCUtil.class.getClassLoader();
            //通过类加载器的getResource方法,我们可以查找当前项目下给定名称的资源的URL
            /*
            public URL getResource(String name)
            查找具有给定名称的资源。资源是可以通过类代码以与代码基无关的方式访问的一些数据(图像、声音、文本等)。
             */
            //查找当前src下文件“jdbc.properties”的URL
//我们发现JDBCUtil类与"jdbc.properties"在同一个根路径src下,因此在src包中的JDBCUtil类可以识别到"jdbc.properties"文件
//那么getResource方法的路径只需要写"jdbc.properties"即可。如果"jdbc.properties"在JDBCDemo这个module
//下的其他包,"jdbc.properties"与JDBCUtil类的最高相同根目录为JDBCDemo,路径应该写作haha//jdbc.properties
            URL res = classLoader.getResource("jdbc.properties");

            //获取“jdbc.properties”文件的绝对路径
// /G:/idea_java_project/java-demo1/out/production/JDBCDemo/jdbc.properties
            String path = res.getPath();
            System.out.println(path);
            //将“jdbc.properties”读取流加载到Properties对象
            //2,加载文件
            p.load(new FileReader(path));


             //3.获取数据,赋值
            url = p.getProperty("url");
            user = p.getProperty("user");
            password = p.getProperty("password");
            driver = p.getProperty("driver");

            //注册驱动
            Class.forName(driver);
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        catch(ClassNotFoundException e)
        {
            e.printStackTrace();
        }
    }

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

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

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

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


//------------------JdbcDemo1类
package lkj.demo.jdbc;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class JdbcDemo1
{
    public static void main(String[] args)
    {
        List<EmpDemo> list = new JdbcDemo1().findAll2();
        System.out.println(list);//太长了
        System.out.println(list.size());//14
    }

    /**
     * 演示JDBC工具类
     * @return
     */
    public List<EmpDemo> findAll2()
    {
        Connection con = null;
        Statement sm = null;
        ResultSet rs = null;
        List<EmpDemo> al = null;
        try
        {
            //首先是注册驱动和获取数据库连接2句不需要写
//            Class.forName("com.mysql.jdbc.Driver");
//            con = DriverManager.getConnection("jdbc:mysql:///db1","root","root");
            //我们使用JDBCUtil类名调用getConection方法,这样JDBCUtil类的静态代码块会被执行
            //既会获取jdbc.properties各个参数,并复制给相应变量。同时注册驱动
            con = JDBCUtil.getConnection();
            sm = con.createStatement();
            String sql = "select * from emp";
            rs = sm.executeQuery(sql);

            EmpDemo emp = null;
            al = new ArrayList<EmpDemo>();

            while(rs.next())
            {
                int id = rs.getInt(1);
                String name = rs.getString("ename");
                int job_id = rs.getInt(3);
                int mgr = rs.getInt(4);

                Date joindate = rs.getDate(5);
                Double salary = rs.getDouble(6);
                Double bonus = rs.getDouble(7);
                int dept_id = rs.getInt(8);

                emp = new EmpDemo();
                emp.setId(id);
                emp.setEname(name);
                emp.setJob_id(job_id);
                emp.setMgr(mgr);
                emp.setJoindate(joindate);
                emp.setSalary(salary);
                emp.setBonus(bonus);
                emp.setDept_id(dept_id);

                al.add(emp);
            }

        }
        catch (SQLException e)
        {
            e.printStackTrace();
        }
        finally
        {
            //其次finally里面的关闭资源可以通过调用方法来实现
            JDBCUtil.close(rs,sm,con);
        }
        return al;
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值