JDBC基础---Oracle篇

一、JDBC技术引言

1.什么是JDBC技术

JDBC,全称Java DataBase Conectivity,JDBC技术即Java数据库连接技术

技术核心:应用Java程序,访问操作数据库,对用户屏蔽SQL的存在,属于底层代码。

2.JDBC的API

在这里插入图片描述

DriverManager:驱动管理类,方便程序员使用Driver和数据库建立连接。
Connection:连接接口,代表JDBC和数据库的连接。
PreParedStatement:代表发送SQL的工具。
ResultSet:结果集接口,代表查询SQL执行之后的结果。

3.JDBC访问数据库的核心思想。

在这里插入图片描述

4.JDBC的编程步骤。

a).导入数据库驱动jar包。 //数据库厂商提供
b).注册(加载)驱动 //告诉虚拟机使用的是哪一个驱动(什么数据库)
c).获得连接 //使用JDBC中的Connection接口,完成对Oracle数据库的连接
d).获得语句执行平台 //通过连接对象获取对SQL语句的执行者对象
e).执行SQL语句 //使用执行者对象,向数据库执行SQL语句,并获取执行结果
f).处理结果 //只有查询操作才需要对查询到的结果做处理
g).释放资源 //就是调用一堆close()

5.日期类型的处理

a).java.util.Date:平时推荐使用的时期类型,不能应用在jdbc操作中。
b).java.sql.Date:特点:代表时间,只能用JDBC操作中。

6.动态参数(数据绑定)

a).字符串拼接

   String sql = "select * from test where name = '"+username+"' and password = '"+userpwd+"'"; 

特点:
1.可能会被SQL注入攻击
2.可以拼接表名、列名、sql关键字
应用场景:动态查询不同的表 根据用户选择进行升序或者降序排列。

b).占位符绑定数据(请查阅PreparedStatementAPI文档翻看setXxx()类型方法)

    String sql = "update test set address = ?,birthday = ? where id = ?";  
    preparedStatement = connection.prepareStatement(sql);  
    preparedStatement.setString(1, "符文之地");  
    java.util.Date date = new java.util.Date();  
    java.sql.Date date2 = new java.sql.Date(date.getTime());  
    preparedStatement.setDate(2, date2);  
    preparedStatement.setInt(3, 3);  
    preparedStatement.executeUpdate();  

特点:
1.可以防止SQL注入攻击
2.不可以拼接表名、列名、sql关键字

7.主键自动增长

a).首先在数据库中创建sequence序列,假设定义名为test_seq
b).test_seq.nextval代替插入传递的主键参数
c). insert into test (id,name,address,birthday) values (test_seq,‘艾希’,‘弗雷尔卓德’,日期);

二、原生JDBC代码

create table test(
   id number(10) primary key,
   name varchar2(20) not null,
   address varchar2(60),
   birthday date
   );
   insert into test (id,name,address,birthday) values (1,'艾希','弗雷尔卓德',sysdate);
   insert into test (id,name,address,birthday) values (2,'厄运小姐','比尔吉沃特',sysdate);
   insert into test (id,name,address,birthday) values (3,'卡特琳娜','诺克萨斯',sysdate);
   commit;
   select * from test;
  

1.增加

@Test
 public void insert(){
  Connection connection = null;
  PreparedStatement preparedStatement = null;
  try {
   //加载驱动,告诉虚拟机要开始使用什么数据库驱动
   Class.forName("oracle.jdbc.OracleDriver");   
   //获取连接,使用JDBC中的类DriverManager中的静态方法getConnection方法获取连接
   connection = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe","hr","hr");
   
   //定义SQL语句,此句测试插入操作
   Date date = new Date();
   java.sql.Date date2 = new java.sql.Date(date.getTime());
   String sql = "insert into test (id,name,address,birthday) values (4,'艾希','弗雷尔卓德',?)";
   
   //conn调用preparedStatement方法创建一个PreparedStatement对象并返回,这个对象相当于一个存放和传递SQL语句的平台,传给数据库
   preparedStatement = connection.prepareStatement(sql);
   preparedStatement.setDate(1, date2);   
   
   //此句一旦执行就表示用当前对象执行SQL语句,执行结束后在数据库中的操作(增删改)也结束
   preparedStatement.executeUpdate();
  } catch (ClassNotFoundException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (SQLException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } finally {
   //关闭资源
   if (connection != null) {
    try {
     connection.close();
    } catch (SQLException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   }
   if (preparedStatement != null) {
    try {
     preparedStatement.close();
    } catch (SQLException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   }
  }
 }

2.删除

@Test
 public void delete(){
  Connection connection = null;
  PreparedStatement preparedStatement = null;
  try {
   Class.forName("oracle.jdbc.OracleDriver");
   connection = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe","hr","hr");
   String sql = "delete from test where id = ?";
   preparedStatement = connection.prepareStatement(sql);
   preparedStatement.setInt(1, 4);
   preparedStatement.executeUpdate();
  } catch (ClassNotFoundException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (SQLException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } finally {
   if (connection != null) {
    try {
     connection.close();
    } catch (SQLException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   }
   if (preparedStatement != null) {
    try {
     preparedStatement.close();
    } catch (SQLException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   }
  }
  
 }

3.修改

@Test
 public void update(){ 
  Connection connection = null;
  PreparedStatement preparedStatement = null;  
  try {
   Class.forName("oracle.jdbc.OracleDriver");
   connection = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe","hr","hr");
   String sql = "update test set address = ?,birthday = ? where id = ?";
   preparedStatement = connection.prepareStatement(sql);
   preparedStatement.setString(1, "符文之地");
   java.util.Date date = new java.util.Date();
   java.sql.Date date2 = new java.sql.Date(date.getTime());
   preparedStatement.setDate(2, date2);
   preparedStatement.setInt(3, 3);
   preparedStatement.executeUpdate();
  } catch (ClassNotFoundException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (SQLException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } finally {
   if (connection != null) {
    try {
     connection.close();
    } catch (SQLException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   }
   if (preparedStatement != null) {
    try {
     preparedStatement.close();
    } catch (SQLException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   }
  }
 }

4.查询

@Test
 public void select(){
  Connection connection = null;
  PreparedStatement preparedStatement = null;
  ResultSet resultSet = null;
  try {
   //加载驱动,告诉虚拟机要开始使用什么数据库驱动
   Class.forName("oracle.jdbc.OracleDriver");
   //获取连接,使用JDBC中的类DriverManager中的静态方法getConnection方法获取连接
   connection = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe","hr","hr");
   //定义SQL语句,此句测试插入操作
   String sql = "select * from test";
   //conn调用preparedStatement方法创建一个PreparedStatement对象并返回,这个对象相当于一个存放和传递SQL语句的平台,传给数据库
   preparedStatement = connection.prepareStatement(sql);
   //此句一旦执行就表示用当前对象执行SQL语句,执行结束后在数据库中的查询操作也结束
   resultSet = preparedStatement.executeQuery();
   //开始处理数据
   while (resultSet.next()) {
    int id = resultSet.getInt(1);
    String name = resultSet.getString(2);
    String address = resultSet.getString(3);
    java.util.Date date = resultSet.getDate(4);    
    System.out.println(id+"\t"+name+"\t"+address+"\t"+date);   
   } 
  } catch (ClassNotFoundException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (SQLException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } finally {
   //关闭资源
   if (connection != null) {
    try {
     connection.close();
    } catch (SQLException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   }
   if (preparedStatement != null) {
    try {
     preparedStatement.close();
    } catch (SQLException e) {
     // TODO Auto-generated catch block
     e.printStackTrace();
    }
   }
  }
 }

5.常见错误

a).为什么程序没有显示错误
原因:catch块中没有 e.printStackTrace();

b).java.lang.ClassNotFoundException产生原因:
1 类名字书写错误
2 没有导入相关的jar包(记得build up with)

c).java.sql.SQLException
与sql语句相关的错误
1.约束错误
2.表名、列名书写错误

d).IO异常: The Network Adapter could not establish the connection
1.oracle服务的监听器问题
2.oracle:jdbc:thin:@ip问题

e).SQL语句书写有误:
1.字符串是单引号
2.在Java定义时,字符串内末尾不加分号
3.SQL语句本身语法有问题

三、原生JDBC的缺点

1.数据库连接,使用时就创建,不使用立即释放,对数据库进行频繁连接开启和关闭,造成数据库资源浪费,影响
数据库性能。使用数据库连接池管理数据库连接。但是现在连接池多种多样,可能存在变化,有可能采用DBCP的连接池,也有可能采用容器本身的JNDI数据库连接池。

**设想:**我们可以通过DataSource进行隔离解耦,我们统一从DataSource里面获取数据库连接,DataSource具体由DBCP实现还是由容器的JNDI实现都可以,所以我们将DataSource的具体实现通过让用户配置来应对变化。

2.将sql语句硬编码到java代码中,如果sql
语句修改,需要重新编译java代码,不利于系统维护。而且在每个功能都会对数据表进行操作,很多时候就会遇到一个SQL重复的问题,几个功能的SQL语句其实都差不多,有些可能是SELECT后面那段不同、有些可能是WHERE语句不同。有时候表结构改了,那么我们就需要改多个地方,不利于维护。

**设想:**将sql语句配置在xml配置文件中,即使sql变化,不需要对java代码进行重新编译。当我们的代码程序出现重复代码时怎么办?将重复的代码抽离出来成为独立的一个类,然后在各个需要使用的地方进行引用。对于SQL重复的问题,我们也可以采用这种方式,通过将SQL片段模块化,将重复的SQL片段独立成一个SQL块,然后在各个SQL语句引用重复的SQL块,这样需要修改时只需要修改一处即可。

针对上述缺点,将引入Java的封装机制与DAO的设计思想对原生代码进行改进。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值