JDBC 学习笔记3

JDBC 学习笔记3

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

例:
1 try {
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     同一个事务在两个不同的时刻读取不同结果
如:
1 T1: select  score  from  t_score  where  id =   48 ;
2 T2: update  t_score  set  score  =  score + 10   where  id  =   48 ;
3 T1: select  score  from  t_score  where  id =   48 ;
解决重复读问题:
让T1在查询语句中加入for update子句,从而把选定的记录加上排他锁;那么T1事务完成之前,其他事务是不能来获取锁资源的。
3、幻影读            Phanton reads          记录数量变化,而不是行记录的列值
1 T1:elcet  count ( * from  t_class  where  classname  =   ' ****** ' ;
2 T2:nsert  into  t_class  values (.);
3      commit ();
4 T1: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.

你可能感兴趣的:(JDBC 学习笔记3)