您的位置:首页 > 大数据

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

2012-05-29 08:14 381 查看
一、大数据集的分页

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);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: