posts - 18,  comments - 1,  trackbacks - 0

上午:

一.JDBC原理概述

 

1,JDBC是一套协议,是JAVA开发人员和数据库厂商达成的协议,也就是由Sun定义一组接口,由数据库厂商来实现,并规定了JAVA开发人员访问数据库所使用的方法的调用规范。

 

2,JDBC的实现是由数据库厂商提供,以驱动程序形式提供。

 

3,JDBC在使用前要先加载驱动。

JDBC对于使用者要有一致性,对不同的数据库其使用方法都是相同的。

 

驱动开发必须要实现Driver接口。

数据库驱动的实现方式

JDBC-ODBC桥接式

JDBC网络驱动,这种方式是通过中间服务器的协议转换来实现的

JDBC+本地驱动,这种方式的安全性比较差。

JDBC驱动,由数据库厂商实现。

 

二.JDBC的API

 

java.sql包和javax.sql包

Driver接口(驱动),在加载某一 Driver 类时,它应该创建自己的实例并向 DriverManager 注册该实例。这意味着用户可以通过调用以下程序加载和注册一个驱动程序

Class.forName("oracle.jdbc.driver.OracleDriver")

DriverManager类(驱动管理器),它可以创建连接,它本身就是一个创建Connection的工厂(Factory)。

Connection接口,会根据不同的驱动产生不同的连接

Statement接口,发送sql语句

ResultSet接口(结果集),是用来接收select语句返回的查询结果的。其实质类似于集合。

 

下午:

三.JDBC应用步骤

1,注册加载一个driver驱动

2,创建数据库连接(Connection)

3,创建一个Statement(发送sql)

4,执行sql语句

5,处理sql结果(select语句)

6,关闭Statement

7,关闭连接Connection。

 

注意:6,7两个步骤势必须要做的,因为这些资源是不会自动释放的,必须要自己关闭

 

访问Oracle的数据库的驱动名字叫ojdbc14.jar,要使用这个驱动程序,要先将他加到环境变量CLASSPATH中。

 

    注册加载驱动driver,也就是强制类加载

    Class.forName(Driver包名.Driver类名)。

 

    Driver d=new Driver类();//注意:这个方法不能用参数来构造

    DriverManager.registerDriver(d);

 

 

    Oracle的Driver的全名oracle.jdbc.driver.OracleDriver

    mysql的Driver的全名com.mysql.jdbc.Driver

    SQLServer的Driver的全名com.microsoft.jdbc.sqlserver.SQLServerDriver

 

    创建连接

    DriverManager.getConnection(String url,String username,String password);

    Connection连接是通过DriverManager的静态方法getConnection(.....)来得到的,这个方法的实质是把参数传到实际的Driver中的connect()方法中来获得数据库连接的。

    Oracle的URL值是由连接数据库的协议和数据库的IP地址及端口号还有要连接的数据库的库名(DatebaseName)

    Oracle URL的格式

    jdbc:oracle:thin:(协议)@XXX.XXX.X.XXX:XXXX(IP地址及端口号):XXXXXXX(所使用的库名)

    例:jdbc:oracle:thin:@192.168.0.20:1521:tarenadb

    MySql URL的写法

    例: jdbc:mysql://localhost:3306/tarena

    SQLServer URL的写法

    例:jdbc:microsoft:sqlserver://localhost:1433/test

 

    java -Djdbc.drivers=驱动的完整类名

 

    使用虚拟机参数,加载驱动 -D表示为虚拟机参数赋值

    java -Djdbc.drivers=oracle.jdbc.driver.OracleDriver:com.mysql.jdbc.Driver

  

四.JDBC基本方法

    DriverManager:如果有多个驱动可用的话,DriverManager会选择其中一个. 

   

    Driver:可以选择固定的驱动

    Driver driver = new oracle.jdbc.driver.OracleDriver();

    String user = "sd0613";

 String password = "sd0613";

 Properties prop = new Properties();

 prop.setProperty("user",user);

 prop.setProperty("password",password);

    driver.connect(url,properties);

   

    executeQuery(sqlString);//返回结果集

    executeUpdate(sqlString);//返回值为该次操作影响的记录条数,create table返回0

    execute(sqlString);

    //适用于不知道具体的操作是什么,返回值是boolean类型的

    //如果返回值是true,代表执行查询操作;否则代表执行更新操作.

   

    ResultSet

    next()方法:

    1.判断是否存在下一条记录

    2.将游标移向下一条记录  

    getXXX(字段名或字段序号)//注意:字段序号从1开始

   

    关闭问题:

    使用Connection对象获得一个Statement,Statement中的executeQuery(String sql) 方法可以使用select语句查询,并且返回一个结果集 ResultSet通过遍历这个结果集,可以获得select语句的查询结果,ResultSet的next()方法会操作一个游标从第一条记录的前边开始读取,直到最后一条记录。executeUpdate(String sql) 方法用于执行DDL和DML语句,可以update,delete操作。

注意:要按先ResultSet结果集,后Statement,最后Connection的顺序关闭资源,因为Statement和ResultSet是需要连接时才可以使用的,所以在使用结束之后有可能其他的Statement还需要连接,所以不能先关闭Connection。



1.回忆下昨天的一些JDBC的配置
 (1) 驱动:  
  ojdbc14.jar (Oracle)                 
  mysql-connector-java-3.1.11-bin.jar(MySql)
 (2) 实现了Driver接口的驱动类(程序中要加载的类):
  jdbc.oracle.driver.OracleDriver  (Oracle)
  com.mysql.jdbc.Driver  (MySql)
 (3)连接数据库的URL
  jdbc:oracle:thin:@192.168.0.24:1521:tarena   (Oracle)
  jdbc:mysql://192.168.0.24:3306/test    (MySql)
         
2.PreparedStatement概述
 SQL语句传到数据库后,数据库会先对其编译再执行。在使用Statement时,如果要执行一组类似的SQL操作时,这样做效率很低,而且把不同类型的数据直接写在SQL语句中是比较麻烦的。这时应该用PreparedStatement来代替Statement,PreparedStatement 接口继承 Statement,并和他在两方面有所不同:
 (1)PreparedStatement 实例包含已编译的 SQL 语句。这就是使语句先“准备好”。包含于 PreparedStatement对象中的SQL 语句可具有一个或多个 IN 参数。IN参数的值在 SQL 语句创建时未被指定。相反的,该语句为每个 IN 参数保留一个问号(“?”)作为占位符。每个问号的值必须在该语句执行之前,通过适当的setXXX 方法来提供。
 (2)由于 PreparedStatement 对象已预编译过,所以其执行速度要快于 Statement 对象。因此,多次执行的 SQL 语句经常创建为 PreparedStatement 对象,以提高效率。
  

 作为 Statement 的子类,PreparedStatement 继承了 Statement 的所有功能。另外它还添加了一整套方法,用于设置发送给数据库以取代 IN 参数占位符的值。同时,三种方法 execute()、 executeQuery() 和 executeUpdate() 已被更改以使之不再需要参数。这些方法的 Statement 形式(接受 SQL 语句参数的形式)不应该用于 PreparedStatement 对象。

3.创建 PreparedStatement 对象
 以下的代码段(其中 con 是 Connection 对象)创建包含带两个 IN 参数占位符的 SQL 语句的 PreparedStatement 对象:
 PreparedStatement pstmt = con.prepareStatement("UPDATE table4 SET m = ? WHERE x = ?");
 pstmt 对象包含语句 "UPDATE table4 SET m = ? WHERE x = ?",它已发送给DBMS,并编译好为执行作好了准备。

 

4.传递 IN 参数
 在执行 PreparedStatement 对象之前,必须设置每个 ? 参数的值。这可通过调用 setXXX 方法来完成,其中 XXX 是与该参数相应的类型。例如,如果参数具有Java 类型 long,则使用的方法就是 setLong。setXXX 方法的第一个参数是要设置的参数的序数位置(从1开始),第二个参数是设置给该参数的值。例如,以下代码将第一个参数设为 123456789,第二个参数设为 100000000:
 pstmt.setLong(1, 123456789);
 pstmt.setLong(2, 100000000);


5.ResultSetMetaData
 元数据是用来描述数据的数据,ResultSetMetaData就是来描述结果集的列的类型和属性信息,比如可以通过它得到结果集的列数,列名等。具体可在API中查阅java.sql.ResultSetMetaData。
 ResultSetMetaData对象可以通过ResultSet对象的getMetaData()来得到。
 ResultSetMetaData对象有以下三个方法比较常用:
 getColumnCount():获得实际列数
 getColumnName(int colnum):获得指定列的列名
 getColumnType(int colnum):获得指定列的数据类型(Types里面的类型,存放的是整数)
 
6.JDBC是持久层的技术,是JAVA连接数据库目前最通用的手段。其他的持久层技术,比如接下来我们要学的Hibernate,底层也是由JDBC实现的。持久层是与业务无关的,具体的业务由业务层完成,当业务层需要和数据库进行交互时,就需要通过持久层来操作。

7.BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
 由于System.in是字节流,我们需要把他转成字符流。并用BufferedReader包装后方便我们的操作。
 
8.为了区分表中不同的数据,我们要给放入表中持久化的每个对象都加上一个唯一的标识,这就是ID,ID是与业务无关的。ID的生成方法有很多,在Oracle数据库中我们一半利用Sequence来生成。

9.读取配置文件时,我们采用Properties对象。它是HashTable的子类,它有个load(InputStream inStream) 的方法可以直接从输入流中读取属性列表(键值对)。getProperty(String key) 方法用指定的键在此属性列表中搜索值。


1.Registering a driver
2.Establishing a connection to the datebase
3.Creating a statement
4.Executing a SQL
5.Processing the results
6.Closing down JDBC objects




JDBC第三天
上午:
一.事务(Transaction)
原子操作:不可再分的操作,一个操作不能再分成比它更细小的操作.
事务是针对原子操作的,要求原子操作不可再分,并且必须同时成功同时失败。
事务就是把一些非原子操作,变成原子操作,由应用服务器来提出要求,由数据库服务器来执行操作.

在JDBC中默认是自动提交的,如果要想使用事务,需要按以下步骤执行:
1.要调用con.setAutoCommite(false)方法(打开事务边界),把自动提交(commit)置为false。
2.进行正常的数据库操作
3.如果操作成功了可以选择con.commit(),或者操作失败时选择con.roolback()------
   (回滚:数据恢复到之前的情况)

  注意:打开事务就要关闭自动提交,当不需要再使用事务的时候调用
setAutoCommite(true).

事务性资源(监控完整性)
 
二.事务并发产生的问题
    三种并发产生的后果:
1,脏读:一个事务读取到了另外一个事务没有提交的数据。(Dirty Read)
2,重复读:一个事务读取到了另外一个事务提交的数据。它是要保持在同一时间点上读取到的数据相同,希望在一段时间内的数据是不变的。
3,幻读:一个事务读取到了另外一个事务提交的数据。用同样的操作读取两次,得到的记录数不相同。

三.事务隔离级别
    五种控制级别:
TRANSACTION_NONE不使用事务。
TRANSACTION_READ_UNCOMMITTED 允许脏读。
TRANSACTION_READ_COMMITTED防止脏读,最常用的隔离级别,并且是大多数数据库的默认隔离级别----------------------
TRANSACTION_REPEATABLE_READ可以防止脏读和不可重复读,
TRANSACTION_SERIALIZABLE可以防止脏读,不可重复读取和幻读,(事务串行化)会降低数据库的效率

以上的五个事务隔离级别都是在Connection类中定义的静态常量,使用setTransactionIsolation(int level) 方法可以设置事务隔离级别。
如:con.setTransactionIsolation(Connection.REPEATABLE_READ);

下午:
四.JDBC2.0新特性
1.可滚动特性和可更新特性
JDBC1.0中是指游标的移动的方向和方式是单向,单步(相对)移动,功能比较简单.
JDBC2.0中游标可以双向,相对或者绝对移动.
可滚动结果集:这种结果集不但可以双向滚动,相对定位,绝对定位,并且还可以修改数据信息。

1)滚动特性
定位函数:aaa
boolean absolute(int row),定位到指定的记录位置。定位成功返回true,不成功返回false。
void afterLast() ,把游标移动到最后一条记录的后面(逻辑位置)。 一定会有的
void beforeFirst() ,把游标移动到第一条记录的前面(逻辑位置)。
//由于第一条记录的前面和最后一条记录的后面这两个位置肯定存在,所以无需判断是否存在,返回值设为void.

boolean first(),把游标定位到第一条记录,相对定位;
boolean last(),把游标定位到最后一条记录   也是相对的概念。

//当结果集为空的时候,这两个方法会返回false.
boolean next(),此方法是使游标向下一条记录移动。
boolean previous() ,此方法可以使游标向上一条记录移动,前提是前面还有记录。

boolean relative(int rows) ,相对定位方法,参数值可正可负,参数为正,游标从当前位置向后移动指定值条记录,参数为负,游标从当前位置向前移动指定值条记录。

判断函数:
ifBeforeFirst()判断是否在在第一条记录之前.
ifAfterLast()判断是否在在最后一条记录之后.
ifFirst()判断是否为第一条记录.
ifLast()判断是否为最后一条记录.

要使用可滚动结果集时,需要一次设置更新特性与滚动特性,不能分开.

1.更新特性常量:
CONCUR_READ_ONLY 只读结果集     (默认的)
CONCUR_UPDATABLE 可更新结果集

2.滚动特性常量:
TYPE_FORWARD_ONLY ,该常量表示指针只能向前移动的 ResultSet 对象的类型。(默认)
双向滚动:
 不敏感:TYPE_SCROLL_INSENSITIVE ,该常量指示可滚动但通常不受其他更改影响的 ResultSet 对象的类型。
 敏感的:TYPE_SCROLL_SENSITIVE ,该常量指示可滚动并且通常受其他更改影响的 ResultSet 对象的类型。
//敏感:数据库改变,结果集改变.
语法:        
Statement st=null;
st=con.createStatement(ReusltSet.TYPE_SCROLL_INSENSITIVE,ResuleSet.CONCUR_UPDATABLE)
在创建Statement的时候就要指定这两个参数,使用Statement,第一个参数代表滚动特性常量,第二个代表更新特性常量


----------------------------------------


2)可更新特性
a.moveToInsertRow();记录当前游标位置,将游标移到和结果集结构类似的缓冲区;
b.使用updateXxx(int column,columnType value)方法来更新指定列数据;
c.使用insertRow() 方法插入记录,加信结果集,更新
d.将游标指回原位,moveToCurrentRow() 。


 2,3步,可循环
-----------------------------------------------------
能否使用JDBC2.0 ResultSet的新特性,要看使用的数据库驱动是否支持.
还有只能用于单表且表中有主键字段(可能会是联合主键),不能够有表连接,会取
可更新操作必须满足以下条件:
a.查询只能引用一张表.
b.不能包含任何连接操作.
c.必须把完整的主键查到结果集里面;
d.保证所有字段为非空字段并且没有默认值。

五.数据库元数据:
DatabaseMetaData dbmd = con.getMetaData();//得到数据库元数据
dbmd.supportsResultSetConcurrency(ResultSet.TYPE_FORWARD_ONLY,
                    ResultSet.CONCUR_UPDATABLE);//判断是否支持可更新操作

六.批量更新
优势:
1.节省传递时间
2.并发处理

PreparedStatement:
1.addBatch() 将一组参数添加到 PreparedStatement对象内部
2.executeBatch() 将一批参数提交给数据库来执行,如果全部命令执行成功,则返回更新计数组成的数组。

Statement:
addBatch(String sql)方法会在批处理缓存中加入一条sql语句
executeBatch()执行批处理缓存中的所有sql语句。

注意:PreparedStatement中使用批量更新时,要先设置好参数后再使用addBatch()方法加入缓存。
批量更新中只能使用更新或插入语句

//
Statement stm=con.createStatement(int resultSetType,int resultSetConcurrency);创建的时候就要指明要什么样的结果集。
  先可滚,后可更新

boolean absolute (int row)绝对定位,

afterLast()定位到最后一条记录的后面

 

 

 

 

 

 

 


 

 

 

 

 

posted on 2007-03-21 16:14 sunny 阅读(1005) 评论(0)  编辑  收藏
<2007年3月>
25262728123
45678910
11121314151617
18192021222324
25262728293031
1234567

常用链接

留言簿(1)

随笔分类

随笔档案

相册

收藏夹

朋友

搜索

  •  

最新评论

评论排行榜