JDBC代码实现之第三版

前言

代码实现之第二版:代码封装与参数提取 我们通过DBTool工具封装了注册驱动,建立、关闭连接的代码,那我们得到连接以后,想执行一个SQL。还需要通过连接创建一个对象叫Statement。
然后呢,调用它的方法执行sql语句。那么,执行DML的方法调这个executeUpdate()。DQL调这个方法executeQuery(),其他的,调这个execute()。

1.准备工作

  • 想执行SQL语句,首先数据库里需要有相应的表存在。新建一个emps表,然后再表中插入几条默认数据。往Oracle里插入数据时,ID使用序列生成,还得需要创建一个序列sequence,在执行DML语句之后需要commit提交,保存更改。
  • 创建员工表:

create table emps (
empno number(8) primary key,
ename varchar(20),
job varchar(20),
mgr number(8),
hiredate date,
sal number(11,2),
comm number(11,2),
deptno number(8)
);

  • 创建序列:

create sequence emps_seq;

  • 插入默认数据:

insert into emps values(emps_seq.nextval,‘张三’,‘领导’,0,sysdate,18000.0,3000.0,1);
insert into emps values(emps_seq.nextval,‘李四’,‘销售’,1,sysdate,7000.0,5000.0,1);
insert into emps values(emps_seq.nextval,‘王五’,‘销售’,1,sysdate,8000.0,2000.0,1);
insert into emps values(emps_seq.nextval,‘马六’,‘市场’,1,sysdate,6000.0,0,1);
insert into emps values(emps_seq.nextval,‘周七’,‘市场’,1,sysdate,5000.0,0,1);
insert into emps values(emps_seq.nextval,‘冯八’,‘市场’,1,sysdate,4000.0,0,1);
commit;

  • 检查数据:

select * from emps;

2.创建Statement对象

创建连接以后,下一步还要创建另外一个对象Statement,这个对象能帮我们执行SQL,在利用Statement对象执行SQL之前,要写好相应的SQL语句。这个Statement在java.sql包下,java.sql.Statement。代码如下:

Statement smt = conn.createStatement();

3.执行DML的SQL语句

基于emps表,以insert为DML语句的代表,演示Statement对象如何执行DML的SQL语句。

  • SQL语句:在emps表中一共有8个字段,所以要写出8列来,第一列用序列生成,其他列的值,按照顺序直接写上去,代码如下(JDBC要求在Java中,sql语句无需写分号结尾):

    String sql = "insert into emps values(emps_seq.nextval, '唐僧', '经理', 0, sysdate, 8000.0, 2000.0, 3)";

  • 执行SQL:执行DML的SQL语句,需要调用Statement对象的executeUpdate()方法。这个方法是有返回值的,它的返回值是个整数,返回的是行数,就是你插入一行数据,则返回1,插入两行,返回2,当然我们插入,肯定就是每个sql就1行,那如果执行的是一个delete语句,它返回的是删除几行,执行update语句,返回的是修改了几行,所以它返回的是增加,或修改,或删除了几行,是一个行数。代码如下:

    int rows = smt.executeUpdate(sql);
    System.out.println(rows);

  • 完整代码示例

    /**
    * 1.测试DBTool.getConnection()
    * 2.执行insert语句
    */
    @Test
    public void test() {
    Connection conn = null;
    try {
    //创建连接
    conn = DBTool.getConnection();
    System.out.println(conn);
    //创建Statement
    Statement smt = conn.createStatement();
    //SQL(不要写分号结束)
    String sql = “insert into emps values(emps_seq.nextval, ‘唐僧’, ‘经理’, 0, sysdate, 8000.0, 2000.0, 3)”;
    //执行SQL
    int rows = smt.executeUpdate(sql);
    //返回增加/修改/删除了几行
    System.out.println(rows);
    } catch (SQLException e) {
    e.printStackTrace();
    } finally {
    DBTool.close(conn);
    }
    }

4.执行DQL的SQL语句

如何执行查询语句,执行DQL语句比执行DML语句要复杂一些,因为,执行DML语句,它直接返回个行数就完了,一般还用不上这个行数,只要执行成功了,它该几行就几行,但执行查询的时候,它查什么就返回什么,我要查10个员工,你把10个员工返回给我,所以,这个返回的数据就多了,那具体要怎么处理返回的数据,就麻烦在此。

  • SQL语句:查询emps这张表,条件部门ID等于1,排个序,结尾不写分号。另外,在正式项目中写SQL语句时,建议不要写select *,因为一个表中可能有很多字段,而业务中一般只需要几个字段,写select * 是比较耗资源的。比如开发的时候,做一个合同的模板。它不是一张表,是关联的表有十几个,而合同的主表有200多个字段,上来就select * 的话,就是不负责任的,具体要看业务需求,要什么,查什么。此处表中字段少,为了省事,写*问题也不大。

    String sql = "select * from emps_lhh where deptno=1 order by empno";

    其他的,在正式项目中写SQL时,建议SQL写成大写的,因为大写的效率高。实际上,JDBC把这个SQL发送给数据库,数据库去执行,Oracle在执行SQL以前,它会把SQL先转成大写,再执行。如果我们直接写成大写的SQL,数据库就跳跃了这一步,节约了一点点时间。但访问的人多了,这个时间就长了,所以这个能提高效率。当平时为了便于阅读,写成小写,在通过开发工具的快捷键,进行大小写转换,

    Ctrl+Shift+X 变大
    Ctrl+Shift+Y 变小

  • 执行SQL:执行DQL的SQL语句,需要调用Statement对象的executeQuery(sql)方法。传入sql,它给我们返回一个特殊的东西,叫做ResultSet结果集对象,查询结果的集合,这个对象里存的是查询到的结果,是多行多列的数据。即查询到的数据以多行多列的形式封装到这个结果集ResultSet对象中。代码如下:

    ResultSet rs = smt.executeQuery(sql);

  • ResultSet:结果集ResultSet对象,它的底层采用的是迭代器模式进行的设计,迭代器模式通常使用while遍历访问(比如遍历Iterator对象也是如此)。通过调用ResultSet的next()方法读取到下一行数据,所以说我们遍历的是行,在获取到某一行数据之后,这一行会有很多列,可以通过调用ResultSet的getXxx()方法分别获取该行的每一列的值(比如rs.getInt("empno");或者rs.getString("ename")),在rs.getXxx()的语法是rs.get类型()的一系列方法,这些方法中需要传入一个参数,这个参数可以写字段的名称,也可以写字段的序号都行,但一般,建议写字段的名,不建议写序号,因为在我们开发的过程中,有可能,这个表将来会发生变化。比如说今年,这个表里20个字段,明年没准多几个字段,或者少了几个字段,这个顺序会有所变化。而字段名,只要字段不删的话,一般不会变。所以一般建议用字段名作参数。
  • 完整代码示例

    @Test
    public void test() {
    Connection conn = null;
    try {
    conn = DBTool.getConnection();
    Statement smt = conn.createStatement();
    //ctrl+shift+x/y
    String sql = “select * from emps where deptno=1 order by empno”;
    //返回的ResultSet是结果集,封装了查询到的结果(多行多列).
    //该对象采用迭代器模式设计而来的. 迭代器通常使用while遍历.
    ResultSet rs = smt.executeQuery(sql);
    //每次next()就可以获取下一行数据
    while(rs.next()) {
    //获取该行的每一列的值
    //rs.get类型(字段的序号)
    //rs.get类型(字段的名称)
    System.out.println(rs.getInt(“empno”));
    System.out.println(rs.getString(“ename”));
    }
    } catch (SQLException e) {
    e.printStackTrace();
    } finally {
    DBTool.close(conn);
    }
    }

5.总结

  • JDBC(Java Database Connectivity): Java访问数据库的解决方案,希望用相同的方式访问不同的数据库,以实现与具体数据库无关的Java操作界面,因此JDBC定义了一套标准接口,即访问数据库的通用API,不同的数据库厂商根据各自数据库的特点去实现这些接口:

    APP——JDBC——JDBC Driver(由数据库厂商实现)——数据库

  • JDBC是属于Java的一部分。这部分技术,Sun只是规定了接口,而没有提供实现。主要因为Sun实现不起,市场上的数据库太多,所以这个接口的实现由数据库的厂商来实现,而数据库厂商提供的实现,我们不叫实现类,我们给它取个学名叫Driver,英文的驱动,那么每一个数据库厂商都有它自己的驱动。那么在开发的时候,选择哪一个驱动需要由我们来指定,并且不用自己去实例化这个驱动类,Sun给我提供了一个类叫DriverManager,它能够帮我们去实例化这个实现类,并帮我们管理驱动,但是,DriverManager给我返回的是接口类型,而它底层的实现new的是具体的实现类。因此,对我们来说,重点是关注这个接口中有什么方法,怎么去调用它们,而不需要关心它的实例化的过程。

  • JDBC的使用步骤:首先,注册驱动,告诉DriverManager驱动管理器,要用哪一套驱动,DriverManager知道信息以后,就能够调用那个驱动里面的实现类,帮我们创建连接,我们得到连接以后,又可以通过连接创建Statement,而这个Statement,它有若干方法,能够执行不同的SQL,其中executeUpdate()执行DML语句,增删改。executeQuery()这个方法执行查询,其他的SQL执行用execute()方法。最后,在使用连接执行完SQL以后,一定要把连接关闭。因为如果不关闭,会长期占用这个数据库的连接,无论是什么数据库,它的连接上限基本上就是五六百个,消耗没了,就很有可能导致数据库的崩溃,所以一定要关闭连接。另外,在JDBC当中,我们并不用在写代码时进行commit操作,因为JDBC默认情况下,在执行完SQL以后,它会自动commit,无需手动commit。当然想改为手动commit也可以。

  • 在jdbc技术中执行executeQuery()方法,会得到一个结果集ResultSet,这个结果集是由迭代器模式设计而来。迭代器模式的特点是,对于一个里面封装了多条数据的集合,通常遍历这个集合的方式,是通过写while循环语句进行遍历,在while遍历集合时,再通过集合中的next()方法进行顺序的获取下一行数据记录,从而将记录中所需要的信息,也就是记录中的列值通过get取出,再对取出的数据进行一系列后续的相关操作。

  • 通过具体的代码演示可以发现,整个创建连接的过程是很麻烦的,一个是创建连接时,需要写一大堆参数,如果每次创建连接都要写这些参数,易错而枯燥,对编程而言会消耗很多时间,很不方便;再一个是在使用JDBC时,几乎每一句话,它都声明抛异常,到处得catch,让代码冗余杂乱,所以为了减少这些麻烦,通过配置文件对参数提取,并不冗余代码封装成一个工具,使其在每次创建连接时得以代码复用,以后创建连接就方便了。那么封装的思路就是管理连接的过程,是根据最终的需求反推过来,而不是一开始就想到的。首先,想法比较简单,就是写一个DBTool工具类,写一个静态方法getConnection(),这个方法能够被调用者调用,给调用者创建连接,然后把创建连接的代码放到这里,复用即可。后来又想到,在创建连接时需要在这个方法中写4个参数,如果在方法中直接写死的话,很不合适,因为软件上线时这个参数是要改的,比如,如果我们做的是一个OA,或者财务的软件产品,卖给不同的公司,卖给一家公司,就要改一遍参数,那么,为了降低修改这个参数的难度,使其改完之后不用开发工具编译,那我们就把这个参数写到一个配置文件里,这个配置文件,如果参数的结构很复杂,通常使用XML,如果参数只是比较简单的结构,就用properties文件,而使用properties文件来存储简单的参数,是Java中非常经典的用法。把参数存到properties里以后,利用Java自带的Properties类进行读取,因为读取操作是比较耗效率的,为了减少读取次数,保证只读一遍,又想到把读取操作写到static静态块中,而读取到的参数是要给getConnection()服务的,最后把参数存到变量之中,以供方法调用获取这些参数。

  • 最终,按照程序的调用过程分析发现,一共是5步:

  1. 写配置文件,要先有配置文件
  2. 写静态块,保证只读取一次配置文件
  3. 声明参数的变量,将读取到的参数赋值给变量
  4. 写getConnection()方法,利用参数变量创建连接
  5. 调用者应用,通过getConnection()方法创建连接
  • 完成对创建连接的代码封装,调用者通过连接执行SQL语句:
  1. 利用过DBTool工具创建一个连接Connection
  2. 调用Connection的createStatement()方法,得到一个Statement对象
  3. 调用Statement对象的方法执行SQL语句:
    (1) 利用executeUpdate执行DML语句的增删改操作,并返回一个被语句影响的行数;
    (2) 利用executeQuery执行DQL语句的查询操作,并返回一个ResultSet结果集对象,ResultSet的底层采用迭代器模式进行的设计,内部存储有多行多列的数据,通常通过wihle语句进行遍历,获取行数据,在通过ResultSet对象中相应的getXxx()方法获取所得行数据的某一列的值。

参考文献(References)

文中如有侵权行为,请联系me。。。。。。。。。。。。。
文中的错误,理解不到位的地方在所难免,也请指教!在成长过程中,也将继续不断完善,不作为专业文章。不喜勿喷。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值