`
java-mans
  • 浏览: 11416120 次
文章分类
社区版块
存档分类
最新评论

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

 
阅读更多

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

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics