JDBC 学习笔记3

在上次的学习笔记中主要说明了一下JDBC的是如何获取DIRVER的的工作原理,以及简单的介绍了一下六个步骤。
今天的笔记主要内容是[JDBC Advanced Topics]异常处理、元数据以及事务。
1、异常 Exception
    java.sql.SQLException          对底层数据库异常的封装,它是一个已检查异常。所以应用程序必须对它做处理。
        .getErrorCode();                获取特定于数据库供应商的错误代码。
    java.sql.SQLWaring extends SQLExecption         提供关于数据库访问警告信息的异常。

例:
1try{
2//此处省略
3}
 catch(SQLException e){
4      while(e != null){
5          e.printStackTrace();
6          e = e.getNextExecption();
7      }

8}

2、元数据:用来描述其他数据的数据
JDBC中的元数据:
ResultSetMetaDate: 结果集元数据,它用来描述结果集本身。
ResultSet.getMetaDate(); 获取当前结果集的元数据。
DatabaseMetaDate: 数据库元数据,用来描述数据库本身。
Connection.getMetaDate(); 获取当前数据库的元数据。

例:
//利用元数据打印出结果集
public void executeSQL(String sqlcommand){
 Connection con 
= null;
 Statement stm 
= null;
 ResultSet rs 
= null;
 
try{
  
//这里的ConnectionFactory是写的一个连接工厂,这里就不做介绍了。
  con = ConnectionFactory.getConnection();
  stm 
= con.createStatement();
  
boolean flag = stm.execute(sqlcommand);
  
if(flag){
   rs 
= stm.getResultSet();
   ResultSetMetaDate rsmd 
= rs.getMetaDate();
   
int columns = rsmd.getColumnCount();
   
for(int i=1;i<columns;i++){
    String columnName 
= rsmd.getColumnLabel(i);
    System.out.print(columnName
+"\t");
   }

   System.out.println();
   
while(rs.next()){
    
for(int i=1;i<columns;i++){
     Object content 
= rs.getObject(i);
     System.out.print(content
+"\t");
    }

    System.out.print();
   }
else{
    
int results = stm.getUpdateCount();
    System.out.println(results
+" resultes was update ");
   }

  }

 }
catch(SQLExecption e){
    
//此处省略若干
 }

}

3、DML的操作 [JDBC的事务] 以事务为单位
JDBC事务:
定义:一组相关的操作,不可分割,一起成功,一起失败。
相关操作:
Connection:
    commit(); JDBC事务提交
    rollback(); JDBC事务回滚
JDBC的事务默认情况下是自动提交的,每执行一次SQL命令,就提交commit一次。[AutoCommit]
如:
转帐(){
    ...
    update t_account1 set balance = balance-100;
    update t_account2 set balance = balance+100;
    ...
}
如何让以上两句SQL语句,一起执行,一起失败。所以就需要把他们放在一个事务中。
如:
转帐(){
    ...
    con.setAutoCommit(false);//关闭自动事务提交
    update t_account1 set balance = balance-100;
    update t_account2 set balance = balance+100;
    如果以上两句都成功,则:
    con.commit();//提交事务
    如果以上任意一个失败,则:
    con.rollback();//事务回滚
}

获取主键方式(主键值生成策略)
主键值不应该由UI界面来收集,而应该由应用程序自动生成,常见的策略如下:
a. max(id)方法
    select max(id) from table_name;
    此方法当有多线程并发时,就会产生问题。
b. sequence 序列
    select sequence.nextval from dual;
    此方法只适用支持序列的数据库产品,所以不是很通用。
c. 维护单行单列得表
1    create table id_table(next_id number not null);
2    insert into id_table next_id values(1);
3    commit;
4    --使用以下SQL自动维护
5    select next_id from id_table for update;
6    update id_table set next_id = next_id+1;
7    commit;

并发控制:多个事务同时操作同一个对象
有三种并发情况,如下:
1、脏读                Dirty reads                读到其他事务没有提交的数据。注:Oracle不支持
2、不可重复读    Repeatable reads     同一个事务在两个不同的时刻读取不同结果
如:
1T1:select score from t_score where id= 48;
2T2:update t_score set score = score+10 where id = 48;
3T1:select score from t_score where id= 48;
解决重复读问题:
让T1在查询语句中加入for update子句,从而把选定的记录加上排他锁;那么T1事务完成之前,其他事务是不能来获取锁资源的。
3、幻影读            Phanton reads          记录数量变化,而不是行记录的列值
1T1:elcet count(*from t_class where classname = '******';
2T2:nsert into t_class values(.);
3    commit();
4T1:selcet count(*from t_class where classname = '******';
5
解决幻影读问题:
锁表:lock table table_name in mode;

事务隔离级别:SUN在JDBC规范中制定了5个级别,分别用来满足不同的并发性。
Connection:
0        .TRANSACTION_NONE                                无
1        .TRANSACTION_READ_UNCOMMITED     可以脏读
2        .TRANSACTION_READ_COMMITED           不可以脏读
4        .TRANSACTION_REPEATABLE                    不可以重复读
8        .TRANSACTION_SERIALIZABLE                  为每个事务都开辟一个空间
事务的隔离界别设置得越高,则并发性能越差
注:不同数据库,对隔离级别的支持也是不一样的。
如:oracle就不支持0和1两种。

如何设置隔离级别?
如:con.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITED);
这个也是默认事务隔离级别。

My Java study notes.

posted on 2008-10-01 23:03 mailguest 阅读(518) 评论(0)  编辑  收藏 所属分类: JDBC


只有注册用户登录后才能发表评论。


网站导航:
 
<2008年10月>
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

导航

统计

公告

~~~~~~JAVA学习笔记~~~~~~

常用链接

留言簿(1)

随笔分类

随笔档案

文章分类

文章档案

搜索

最新评论

阅读排行榜

评论排行榜