JDBC 大資料集分頁 ,大資料讀寫及事務的隔離級別

時之沙發表於2012-05-29

一、大資料集的分頁
1、記憶體分頁:將資料全部取出來放到List中,然後再進行分頁。(不可取的)
2、資料庫層分頁:按照頁碼從資料查詢。
 MySQL:Select * from table limit M,N
  M:開始記錄的索引
  N:取出的條數
假設每頁顯示10條記錄
第一頁資料:select * from customer limit 0,10;
第二頁資料:select * from customer limit 10,10;

每頁開始記錄的索引=(頁碼-1)*10
總共有多少頁:總記錄數%10==0?總記錄數/10:總記錄數/10+1
總記錄數:select count(*) from customer;

Dao:
 int getTotalCount();//獲取總記錄數
 List<Customer> findCustomer(int startIndex,int pageSize);

3、其他需要分頁的業務該怎麼編寫

a、Dao:需要兩個分頁的方法
 int getTotalCount();//獲取總記錄數
 List<Customer> findCustomer(int startIndex,int pageSize);//startIndex開始記錄的索引
        //pageSize每頁顯示的記錄數
b、Service:將分頁相關的資料封裝到Page物件中
 public Page findCustomers(int pagenum);//pagenum使用者要檢視的頁面
 用以下程式碼進行實現該方法
 public Page findCustomers(int pagenum) {
  int totalrecord = dao.getTotalCount();
  Page page = new Page(totalrecord, pagenum);
  List<Customer> cs = dao.findCustomer(page.getStartIndex(), page.getPagesize());
  page.setList(cs);//一定要把分頁的結果放到page物件中
  return page;
 }
c、Servlet:獲取使用者要檢視的頁面,呼叫service層獲得page物件,封裝資料,轉向顯示頁面。
 注:不要忘記設定page物件的url屬性。該屬性指向處理分頁的Serlvet的url地址,比如/servlet/SomeServlet
d、jsp:用於顯示分頁資料
 分頁資料用靜態包含的形式把page.jsp包含進來。page.jsp不需要做任何的修改
二、2.1大資料的讀寫
      BLOB:
   //從結果集中得到BLOB物件的二進位制輸入流
     InputStream in  = resultSet.getBinaryStream(i);
     InputStream in  = resultSet.getBlob(i).getBinaryStream();
      //設定BLOB預編譯,根據絕對路徑得到輸入流, //注意length長度須設定,並且設定為int型,利用File獲取
        PreparedStatement. setBinaryStream(i, inputStream, length);
    
   CLOB:
    獲取:
    reader = resultSet. getCharacterStream(i);
    reader = resultSet.getClob(i).getCharacterStream();
       string s = resultSet.getString(i);
     設定:
    String path = classLoader();
    File f = new File(path);
    PreparedStatement.setCharacterStream(index, reader, length);
    //注意length長度須設定,並且設定為int型,利用File獲取
    2.2 批處理
    實現批處理有兩種方式,第一種方式:
  Statement.addBatch(sql)  list
  執行批處理SQL語句
  executeBatch()方法:執行批處理命令
  clearBatch()方法:清除批處理命令
  
        Connection conn = null;
  Statement st = null;
  ResultSet rs = null;
  try {
  conn = JdbcUtil.getConnection();
  String sql1 = "insert into user(name,password,email,birthday)
   values('kkk','123','abc@sina.com','1978-08-08')";
  String sql2 = "update user set password='123456' where id=3";
  st = conn.createStatement();
  st.addBatch(sql1);  //把SQL語句加入到批命令中
  st.addBatch(sql2);  //把SQL語句加入到批命令中
  st.executeBatch();
  } finally{
   JdbcUtil.free(conn, st, rs);
  }
  採用Statement.addBatch(sql)方式實現批處理:
  優點:可以向資料庫傳送多條不同的SQL語句。
  缺點:
  SQL語句沒有預編譯。
  當向資料庫傳送多條語句相同,但僅引數不同的SQL語句時,需重複寫上很多條SQL語句
  
  實現批處理的第二種方式:
  PreparedStatement.addBatch()
  注意記憶體溢位問題
  具體應用時需要進行細化分批處理
  conn = JdbcUtil.getConnection();
  String sql = "insert into user(name,password,email,birthday) values(?,?,?,?)";
  st = conn.prepareStatement(sql);
  for(int i=0;i<50000;i++){
  st.setString(1, "aaa" + i);
  st.setString(2, "123" + i);
  st.setString(3, "aaa" + i + "@sina.com");
  st.setDate(4,new Date(1980, 10, 10));

  st.addBatch();
  if(i%1000==0){ //每1000條處理一次,處理完進行清零
  st.executeBatch();
  st.clearBatch();
  }
  }
  st.executeBatch();//超出的部分也需要按一次批處理執行

  採用PreparedStatement.addBatch()實現批處理
  優點:傳送的是預編譯後的SQL語句,執行效率高。
  缺點:只能應用在SQL語句相同,但引數不同的批處理中。因此此種形式的批處理經常用於在同一個表中批量插入資料,或批量更新表的資料。
  
  2.3 得到資料庫自動生成的主鍵 
  eg:
  Connection conn = JdbcUtil.getConnection();

  String sql = "insert into user(name,password,email,birthday)
     values('abc','123','abc@sina.com','1978-08-08')";
  PreparedStatement st = conn.
     prepareStatement(sql,Statement.RETURN_GENERATED_KEYS );

  st.executeUpdate();
  ResultSet rs = st.getGeneratedKeys();  //得到插入行的主鍵
  if(rs.next())
   System.out.println(rs.getObject(1));
    2.4JDBC呼叫儲存過程
     編寫儲存過程
  delimiter $$

  CREATE PROCEDURE demoSp(IN inputParam VARCHAR(255), INOUT inOutParam varchar(255))
  BEGIN
   SELECT CONCAT('zyxw---', inputParam) into inOutParam;
  END $$

  delimiter ;
     得到
     CallableStatement stmt = conn.prepareCall("{call demoSp(?,?)}");
  設定引數,註冊返回值並輸出
  stmt.setString(1, "abcde");
  stmt.registerOutParameter(2, Types.VARCHAR);
  stmt.execute();
  System.out.println(stmt.getString(2));
  
  result: zyxw---abcde

三、事務的入門 

    當Jdbc程式向資料庫獲得一個Connection物件時,預設情況下這個Connection物件會自動向資料庫提交在它上面傳送的SQL語句。若想關閉這種預設提交方式,讓多條SQL在一個事務中執行,可使用下列語句:
JDBC控制事務語句
    //開啟事務
     conn.setAutoCommit(false);
 //提交事務
     conn.commit();
    //設定事務儲存點
        SavePoint sp = conn.setSavePoint();
    //事務回滾//回滾後必須要提交
        conn.rollback(sp); 
  conn.commit();
   
四、事務的隔離級別
事務的特性:
原子性(Atomicity) 原子性是指事務是一個不可分割的工作單位,事務中的操作要麼都發生,要麼都不發生。?
一致性(Consistency) 事務必須使資料庫從一個一致性狀態變換到另外一個一致性狀態。
隔離性(Isolation) 事務的隔離性是多個使用者併發訪問資料庫時,資料庫為每一個使用者開啟的事務,不能被其他事務的運算元據所干擾,多個併發事務之間要相互隔離。
永續性(Durability) 永續性是指一個事務一旦被提交,它對資料庫中資料的改變就是永久性的,接下來即使資料庫發生故障也不應該對其有任何影響
事務的異常情況:
髒讀:
指一個事務讀取了另外一個事務未提交的資料。

不可重複讀(針對一條記錄的,同一條記錄前後不一樣)
在一個事務內讀取表中的某一行資料,多次讀取結果不同。

虛讀(幻讀,同一張表前後不一樣記錄數)

 

1、READ UNCOMMITTED:髒讀、不可重複讀、虛讀都可能發生
2、READ COMMITTED:可以防止髒讀,不可重複讀、虛讀有可能發生
3、REPEATABLE READ:可以防止髒讀、不可重複讀,虛讀有可能發生
4、SERIALIZABLE:可以防止髒讀、不可重複讀、虛讀的發生。(鎖)

 注意:設定事務的隔離級別必須在開啟事務之前,否則無法生效

eg:

  conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
  conn.setAutoCommit(false);

相關文章