JDBC学习-JDBC入门

JDCB概念

Java Database Connectivity,数据库连接。
何谓JDBC,我们要使用java语言来操作数据库,然 数据库有很多种,每种的规则可能都有区别,不可能针对特有的数据库来针对操作,效率太低,所以这里sun公司定义了一套操作所有关系型数据库的接口。让所有的数据库来为这个接口创建实现类,(实现类就是数据库驱动)。所以,java程序员只需要使用JDBC来编程即可,不用再管数据库的特性。这里的思想其实跟之前的JVM很像,用同一的java语言来运行在不同的OS上,从而达到可移植性。可见java语言一直都在遵循这个理念。
总而言之。其实是官方(sun)定义的一套操作所有关系型数据库的规则–接口。各个数据库厂商去实现这套接口,提供数据库驱动jar包。我们可以使用这套接口jdbc来编程,真正执行的代码是驱动jar包中的实现类。JDBC是沟通代码与数据库的桥梁

使用步骤

//        1.导入驱动jar包
//        2.注册驱动
        Class.forName("com.mysql.jdbc.Driver");
//        获取数据库连接对象
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1", "root", "root");
//       定义sql语句
        String sql = " UPDATE student SET age = 20;";
//       获取执行sql的对象statement
        Statement stmt = conn.createStatement();
//        执行sql
        int count = stmt.executeUpdate(sql);
//        处理结果
        System.out.println(count);
        stmt.close();
        conn.close();

  1. 导入驱动jar包
    因为上面我们也说到JDBC是一套接口嘛,也不知道你具体使用的是哪个数据库,所以这里需要手动导入你所用的数据库的jar包(驱动)。把jar包放到目录的附近,把路径添加进去。这里不做赘述。其中可能会遇到一些问题,可以见我的另外一篇博客。
  2. 注册驱动
    这一步是为了让程序知道我们的驱动。这里用到了forName()方法,该方法返回传参字符串名称的类或接口对象,也就是输入类名或接口名,返回对象。我们这里传入的是JDBC实现类(驱动类),它会返回一个对象,明显这里没有接收对象,因为我们需要的是注册驱动,而不是这个驱动类对象。在Driver类的源码中,存在着静态代码块,众所周知,静态代码块随着类的加载而执行,只执行一次。在此类的静态代码块中,有这样的java语句:java.sql.DriverManager.registerDriver(new Driver())};即注册驱动。
  3. 获取数据库的连接对象
    上面的代码是通过DriverManage的静态方法getConnectio()来获得的,其实在实际使用过程中,这种方法比较低效,一般采用从数据库连接池中获取连接对象的方式。(就像多线程过程中,我们通过线程池获取线程一样)。数据库连接池我们下面再讲。
    连接对象需要传入数据库的ip地址,端口,还有用户名与密码,用以连接。其实说是连接,这里不妨将其认作成数据库的登录操作。登录的时候,我们需要进入登录页面,然后啪啪啪输入我们的账号信息。
    这里需要注意第一个传参,除了ip和端口,形式固定,切勿写错,否则报错。
  4. 定义SQL语句
    我们这里定义SQL语句是用字符串的形式,这里其实有两种SQL语句。一种是上面这种全是字符串,叫做静态SQL语句,一般是不使用的,因为存在SQL注入安全问题,且效率不高;还有一种就是预编译SQL,一般用这个,效率高,我们下面会详细讲。
  5. 获取执行SQL语句的对象statement
    我们从连接对象那里获得操作对象Statement。
  6. 执行SQL,获取返回结果
    利用我们的操作对象,把要执行的SQL语句放进去,然后就会得到返回结果。
  7. 处理返回结果
    返回结果各式各样,有它固定的形式。
    如果是查询操作,结果是一个结果集ResultSet,这个结果集像是一个表格一样的东西,我们还得对这个表格进行处理。结果集我们下面介绍。
    而如果是更新操作,结果是更新的行数,我们可以通过这个行数来判断是否更新成功,或是更新的情况。
  8. 释放资源
    要养成好的习惯,对于这里释放资源,如果是穿件的连接对象,会直接释放;如果是从数据库连接池中获取的数据库连接对象,则会返回数据库连接池。代码一样,无需改变,这里妙极了。

这里各个对象的获取都是层层递进的,从DriverManage那里输入数据库信息,获取连接对象,再从连接对象那里获取执行对象Statement,之后往执行对象中传入SQL语句进而执行。

JDBC相关接口

Connection
数据库的连接对象,有了这个连接对象,说明已经连接上了数据库。这个类有很多的方法,我们暂时一开始接触的只有CreateStatement()方法(获取数据库执行对象)与事务的提交,回滚,等相关的方法。具体的看api即可

Statement
此类是执行静态SQL,其实基本不用使用这个

ResultSet
结果集,其中封装着查询的结果。
我们可以把查询的结果看成是下图
在这里插入图片描述
一张表,对,就是一张表。查询的结果可不就是一张表嘛。如何对这张表进行处理呢,我们要获取比如第二行第一个数据lisa怎么获得呢。
这里要有一个概念,就是游标,或者你可以理解成光标。一开始我们的光标是指在第一行的,第一行没有数据,它是表头。
如果我们要读取第二行第一数据,我们是不是得把光标往下移一个,这里我们使用ResultSet中的next()方法,光标向下移动一行,它的返回值是boolean类型,如果当前行是最后一行末尾,放回false,不是就返回true。
然后到达了第二行之后,我们需要后去第一个数据,这里有get类型(参数1,参数2)方法,参数1是int类型,代表列的编号,而参数2是列名。通过这个方法,我们可以获取第二行第一个数据。代码如下

//        向下移动一行
        rs.next();
//        选择第一个 这里计数是从1起的
        rs.getString(1);

PreparedStatement
这个与Statement类似,但是处理预编译SQL的。
具体的使用比较简单,只是与Statement有些区别。
首先我们使用的SQL语句不再是静态的,而是预编译的,其中采用?为占位符,在获取执行对象PreparedStatement时就把SQL语句传入,之后呢便是给?赋值,再然后是执行SQL,(因为先前已经传如了SQL,这里便不需要再传入SQL语句),这里便是PreparedStatement与Statement在使用上的区别。

静态SQL与预编译SQL

静态SQL,像我们上面代码示例那样就是静态SQL,同时,下面的例子也是静态SQL

String sql = "select* from user where username = '"+username+"' and password = '"+password+"'";
            //获取执行sql的对象
 stmt = conn.createStatement();
            //执行查询
 rs = stmt.executeQuery(sql);

,这种由字符串拼接而成的都是静态SQL,虽然其中包含着变量,但也是静态SQL。
在网上所有查询静态SQL与预编译SQL,基本都是说静态SQL在编译期就已经确定,而预编译需要到运行时才能确定SQL语句。
在API文档中关于Statement的叙述中写道:用于执行静态SQL语句并返回其生成的结果的对象,在PreparedStatement的叙述中写道:用于执行预编译SQL语句。
而在上面的例子中,明显在编译期是不能确定SQL语句的,因为其中是有变量的,只有到运行时才能确定,所以我在这纠结了好久,也得不到什么答案。可能这个编译并不适用于这里的JABC。
但这里我们可以这样理解区别,结合PreparedStatement对象使用预编译SQL语句来看看:

 String sql = "select * from user where username = ? and password = ?";
            PreparedStatement pstmt = conn.prepareStatement(sql);
            pstmt.setString(1,"root");
            pstmt.setString(2,"root");
            pstmt.executeQuery();
            

通过两段代码可以看到明显的区别:

  • 首先在于SQL语句上,静态SQL语句的是采用字符串拼接,而动态SQL语句是一条完整的字符串,没有拼接;在静态SQL语句中有着变量,而动态SQL语句中是用?来作为占位符。
  • 因为静态SQL语句是字符串拼接,其中包含变量,变量是本身就有值的,而预编译SQL语句是有占位符的,需要之后再调用setXxx来定义值。
  • 在静态SQL语句的执行上,是先通过连接对象获得Statement对象,之后在执行时才会把SQL语句传入;而预编译SQL语句是在通过连接对象获取PreparedStatement时就传入了SQL语句,之后再确定其中的值(即确定全部SQL语句),然后在执行时不用再传入SQL语句

静态SQL语句在传入Statement时已经是确定的,而在预编译SQL语句传入PreparedStatement时是没有确定的,之后还可以确定。
除了这个,静态SQL语句存在的问题是有的,比如上面代码示例,可能用户输入SQL语句关键字,就会导致SQL语句偏离程序员的意图,变得不可控(老生常谈的登录问题,输入or 1=1 会使得条件永远为真),而预编译SQL语句是不存在这个问题的,因为占位符那里这能输入参数,关键字是无效的,因为这里从静态SQL直接嵌入语句编程了传参进入语句。
在静态SQL与预编译SQL的速度上,我用林信良所写的《java学习笔记》中的一段话来说明:在驱动程序支持的情况下,使用PreparedStatement,可以将SQL描述与编译为数据库的执行命令。由于已经是数据库的可执行指令,执行速度会快很多,而使用Statement对象,是在执行时将SQL直接送到数据库,由数据库做剖析、直译再执行,速度就慢很多

数据库连接池

为什么要使用数据库连接池?
存放数据库连接的容器,当系统初始化之后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后,会讲连接对象归还给容器。
这里数据库连接池其实就跟我们的多线程连接池一个道理。
与JDBC一样,数据库连接池也是SUN公司定义的接口DataSource,由数据库厂商来实现,具体使用也要导入jar包,具体使用不赘述。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值