JDBC

JDBC
----------------------------------------------------------------------------------------------------------
1.引入数据库的必要性
课时安排:
第一天理论性的对JDBC介绍,如何使用JDBC以及步骤;
第二天,JDBC特性;
第三天,JDBC核心特性和标准扩展;
第四天,OOAD Datadesign
第五天,行集的操作;
2.JDBC概念
1996年,sun公司提出,一般认为是java database connectivity;JDBC TM(trademark);
作用:规避数据库的不同,为程序开发人员访问数据库提供统一的编程接口,即为API;
3.odbc概念
open database connectivity 基于C语言的,由microsoft提出;
4.jdbc API
是java程序开发人员访问数据库的标准接口,实际上就是一组java语言编写的java类;
   jdbc可以做什么?
答:和数据库建立连接,发送sql语句,处理数据库返回的结果集.
   jdbc API分类
应用程序开发接口 这个接口是统一的....
驱动程序开发接口 数据库开发厂商提供,不同数据库是不同的,如:oracle实现等等....
我们当然主要关注的是应用程序开发接口。
5.jdbc driver的四种类型
  第一种:jdbc-odbc桥+odbc 将jdbc调用转换为odbc调用,性能低;
application->jdbc-odbc桥->odbc->datebase.
  第二种:本地API部分用java编写的驱动,将jdbc调用转换为dbms的调用,
必须安装与数据库相关的客户端程序;
application->jdbc driver(type2)->database client library->database.
  第三种:jdbc网络纯java的驱动,将jdbc调用转换为与dbms无关的网络协议,
然后由相应服务器转换为dbms调用;
appliaction->jdbc driver(type3)->server->database.
  第四种:本地协议纯java的驱动,将jdbc调用转换为dbms的调用
application->jdbc driver(type4)->database.
现实中一般使用第四种;
6.URL:uniform resource locator
网络协议 :http://www.google.com
数据库url:jdbc:<子协议>:<子名字>
例如:jdbc:oracle:thin:@192.168.1.200:1521:briupdb //第四种驱动
     jdbc:oracle:oci:@192.168.1.200:1521:briupdb //胖客户端,第二种驱动
不同厂商的url定义格式是不相同的;
------------------------------------------------------------------------------------------
       如何使用JDBC
7.JDBC编程的步骤
  1.注册驱动
     a.通过类装载器
        Class.forname(driverName)
     b.直接实例化驱动
DriverConstructor dri=new DriverConstructor();
DriverManager.registerDriver(dri);
     c.通过jdbc.drivers属性
外部向java程序传递参数的两种方式:
        1.program参数:
java Test a b c
程序中通过String[] args获取
2.jvm参数:
java -Dname=briup -Dage=20 Test
程序中通过
Properties props=System.getProperties();
String param=props.getProperty("XXXX");获取
java -Djdbc.drivers=driverName[:driverName2:...]
例如:-Djdbc.drivers=oracle.jdbc.driver.OracleDriver
  2.建立连接
a.通过DriverManager:
Connection con=DriverManager.getConnection(url,user,password);
b.通过java.sql.Driver
Connection con=driver.connect(String url,Properties info);
知道properties的使用方法;
  3.创建statement:statement用来发送要执行的sql语句
a.Statement:执行不带参数的sql语句,创建:connection.createStatement()
b.PreParedStatement:执行带参数或不带参数的预编译的SQL语句,
 下次执行的时候就不要编译和优化了;
 创建:connection.prepareStatement()
c.CallableStatement:调用数据库中的存储过程或函数等等,PL/SQL
创建:connection.parpareCall();
b和c称为同构的Statement,a称为异构的Statement.
  4.执行sql语句
statement.executeQuery(); 返回类型ResultSet
statement.executeUpdate();返回类型int,执行此sql语句所影响的记录数.
statement.execute();返回类型boolean,代表执行此语句是否有resultset返回,有就是ture.
  5.处理结果集
只有select语句才会有结果集返回;
while(rs.next()){ //rs是一个游标,初始时在第一条记录的上面一行.
         //每next一次,向下一行.
rs.getString(1);
rs.getInt(2);
}
可以使用位置标识,也可以使用列名来标识(当结果集字段比较多的时候用列名标识法,可以增强程序的可读性)。
  6.释放资源
一般写在finally语句块中.所释放的资源一般有ResultSet,Statement,Connection
---------------------------------------------------------------------------------------------------------
8.建立连接的步骤
String driver="oracle.jdbc.driver.OracleDriver";
String url="jdbc:oracle:thin:@192.168.1.200:1521:briupdb";
String user="briup";
String password="briup";
//建立几个以后关闭几个哦
Connection con=null;
Statement stm=null;
ResultSet rs=null;
try{
//1.注册驱动
Class.forName(driver);
//2.建立连接
con=DriverManager.getConnection(url,user,password);
//3.创建statement
stm=con.createStatement();
//4.执行sql语句
rs=stm.executeQuery("select * from student");
//5.处理结果集
while(rs.next()){
String name=rs.getString(1);
int age =rs.getInt(2);
System.out.println("name:"+name+"age:"+age);
    }
   }catch(Exception e){
e.printStackTrace();
   }finally{
   //6.释放资源,将其放在finally中
if(rs!=null){
try{
rs.close();
}catch(SQLException e){
e.printStackTrace();
}
}
if(stm!=null){
try{
stm.close();
}catch(SQLException e){
e.printStackTrace();
}
}
if(con!=null){
try{
con.close();
}catch(SQLException e){
e.printStackTrace();
}
}
--------------------------------------------------------------------------
9. Statement接口的比较
        答: | Statement | PreparedStatement | CallableStatement
  写代码位置 | 客户端    | 客户端            | 服务器端
  写代码位置 | 客户端    | 服务器端          | 服务器端
编写代码技术 | Java,SQL 操作 |Java,SQL 操作| 数据库的程序语言,如PL/SQL
    可配置性 | 高        |第一次高,以后低   | 低
    可移植性 | 高        |假设支持PreparedStatement的话高
    传输效率 | 低        |第一次低,以后高   | 高
-------------------------------------------------------------------------------------------
java中的异常是对象,所有异常的父类是java.lang.Throwable。
java中异常采用冒泡处理机制。
Error:没有办法处理;
Exception:可以进行处理。
uncheck exception:不需要进行处理,如:空指针异常,数组越界等等。
check exception:所有实现了exception,必须对其进行处理,否则报错;
要么用try...catch捕获;要么继续向上抛出。
----------------------------------------------------------------------------------------------------------
JDBC中的异常
 
SQLWarning
appliaction-----------jdbc------------database
可能抛出异常SQLException
getMessage()
printStackTrace()
自定义异常的目的:为客户提供通俗易懂的错误信息。
java.sql.Connection,Statement,ResultSet===>SQLWarning getWarnings()
metadata:用来描述其它数据的数据。
DatabaseMetaData:用来描述数据库信息的数据,如:数据库的版本号,数据库的名字等;
可以通过Connection.getMetaData()方法获取;
ResultSetMetaData:用来描述结果集信息的数据,如:结果集中有多少列,列的名字,列的类型等等;可以通
过ResultSet.getMetaData()方法获取。
Transaction:事物,一组相关的操作组合为一个整体,要么同时成功,要么同时失败。
ACID四大属性:
    autimicity:原子性;
    consistensy:一致性;
    isolation:隔离性;
    durability:持久性。
事务的提交方式
自动式:jdbc新建连接默认使用此方式;
手动式:Connection.setAutoCommit(false),Connection.commit(),Connection.rollback()
dirty read(脏读):一个事务读取了其他事务未提交的数据。
repeatable read(不可重复读):在同一事务内多次读取同一数据的内容不一致。关注的是内容;
phantom read(幻影读/虚读):在同一事务中多次读取数据库记录的个数不一致。关注的是个数;
---------------------------------------------------------------------------------------------------------
五种隔离级别
为防止以上问题的出现,在JDBC中提供了五种隔离级别:
下面的常量在java.sql.Connection中:
TRANSACTION_NONE 不支持事务
TRANSACTION_READ_UNCOMMITTED 可以读取其他事务未提交的数据,可能产生脏读,不可重复读,幻影读的问题;
TRANSACTION_READ_COMMITTED 只能读取别的事务提交了的数据,解决脏读问题,但仍能产生不可重复读和幻影读问题
TRANSACTION_REPEATABLE_READ 可以解决脏读,不可重复读问题,但仍可能产生幻影读的问题

TRANSACTION_SERIALIABLE 解决了脏读,不可重复读,幻影读的问题
级别设置越高,消耗资源就越高;
------------------------------------------------------------------------------------------
脏读:B事务读到了A事务没有提交的数据
时间A事务B事务
-----------------
t1 启动
t2 启动
t3 update
t4 select
t5 rollback
t6 结束
不可重复读:B事务两次查询同一条记录的内容不一样
时间A事务B事务
-----------------
t1 启动
t2 启动
t3 select
t4 update
t5 commit
t6 结束
幻读:B事务做同一条记录的查询,但结果数量不同
时间A事务B事务
-----------------
t1 启动
t2 启动
t3 select
t4 insert
t5 commit
t6 select
t7 commit
---------------------------------------------------------------------------------------------------------
设置隔离级别的方法:Connection.setTransactionIsolation(隔离级别对应的常量)。
read uncommited read commited repeatable serializable
dirty read n y y y
repeatable read n n y y
phandom read n n n y
oracle 默认的隔离级别是:read commited.
oracle只支持标准的隔离级别中的两种:read commited和serializable.
--------------------------------------------------------------------------------------------------------

JDBC2.0新特性
ResultSet的增强:
可滚动性:jdbc2.0中的ResultSet既可以向前滚动next(),又可以向后滚动previous;
对于指向结果集的游标可以进行绝对定位absolute()和相对定位relative();
对于其它人的修改,结果集可以是敏感的,也可以是不敏感的。
connection.createStatement(ResultSet是否敏感,ResultSet是否可更新),
con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);
ResultSet是否敏感:TYPE-SCROLL-INSENSITIVE,TYPE-SCROLL-SENSITIVE
ResultSet是否可更新:CONCUR-READ-ONLY,CONCUR-UPDATABLE
可更新性:对ResultSet的delete,update,insert操作,影响到数据库
Statement的批处理:可以减少与数据库的交互次数,提高系统的性能;
-------------------------------------------------------------------------------------------
JDBC对标准的扩展:1.0中所没有的东西哦!
Connection pooling:连接池; 
它的作用:提高性能,多用户共享少量的数据物理连接数;
写连接池:
1.在应用启动时,创建一定量的连接放到池中;
2.从连接池中获取一个连接;
3.使用后,将连接重新放到池中;
4.应用关闭时,释放所有连接;
建立类com.briup.extension.PoolManager.java
DataSource:用来获取Connection的工厂,可认为是DriverManager的替代者,一般结合JNDI一起使用
JNDI
JNDI:java naming and directory interface.
client JNDI Service server
client logic name------>logic name------> data source
JNDI编程:
server:将逻辑名与具体资源进行绑定
client:通过逻辑名查询具体资源
放在javax.naming.*,最常用的是Context.其实就是配置一些相关的信息;
模板:
建立com.briup.orm
-------pojo
面向接口的编程:多人编程时,可以在工作未完成之间协同开发,因为每个人的具体细节,对他人可以回避.这就
是接口的特点.
分布式事务:一个事务可能跨越多个数据库,需要由事务管理器帮助我们同一地管理事务。使用两阶段提交协议。

应用服务器:Tomcat,Jboss,IBM websphere,BEA weblogic...
RowSet:有一些数据库驱动不支持结果集的可滚动性和可更新性,这时候可以使用行集;但是目前主流的数据
库都支持结果集的可滚动性和可更新性;
----------------------------------------------------------------------------------------------------------
DAO:data access Object
DAO模式=Data Accessor模式+Active Domain Object模式
1.Data Accessor模式:实现数据访问和业务逻辑的分离,使用接口进行降低耦合;就是我们的DAO类;
2.Active Domain Object模式:实现业务数据的对象化封装;就是我们的user类,实现业务数据的封装;
O/R Mapping===>Object Relation Mapping其实准确的内涵是:对象/关系数据库映射。