JDBC 大数据集分页 ,大数据读写及事务的隔离级别

长平狐 发布于 2012/09/03 12:30
阅读 258
收藏 1

一、大数据集的分页
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);


原文链接:http://blog.csdn.net/t12x3456/article/details/7611330
加载中
返回顶部
顶部