在实际开发工做中,有关于jdbc的应用,常常性地会出现如下五个问题:java
增长或修改查询语句来优化查询结果mysql
eg.:读取数据库表中全部的记录,千万级的记录的读取可能会出现java的内存溢出异常OutOfMemoryErrorsql
缘由分析:java程序是运行在java虚拟机中的,jvm是有内存大小限制的,当咱们把大量的记录一次性地读入jvm的内存中的时候,读出的数据若是超出了jvm所规定的内存最大值的时候就会出现内存溢出的错误。数据库
解决办法:既然内存容量是有限的,咱们能够读取一部分数据进行处理,处理完毕以后在进行下一部分数据的读取,这样避免一次性地载入过多的数据致使内存的溢出。jvm
在jdbc中是如何具体实现的呢?优化
游标的开启:编码
须要在加载驱动后,得到与数据库的链接的同时需啊哟啊在url后面加上?useCursorFetch=trueurl
表示咱们对这个数据库的读取须要使用游标spa
要是使用有标的话,必须使用PreparedStatement 的setFetchSize();code
入参为int型的整数,表示jdbc从数据库中一次读取记录的数量,须要在查询executeQuery以前须要设置一次查询的记录的数量。
import java.sql.*; public class Test001 { private String driver = "com.mysql.jdbc.Driver"; private String url = "jdbc:mysql://host:port/dataBaseName"; private String userName = "xxx"; private String passWord = "xxx"; public void Test() { Connection connection = null; String sql = null; PreparedStatement prepareStatement = null; ResultSet rs = null; try { //装载驱动 Class.forName(driver); //获取链接 connection = DriverManager.getConnection(url,userName,passWord); //变动url设置 url = url + "userCursorFecth = true"; //sql语句 sql = "select * from tableName where sex = Female"; //执行sql语句 prepareStatement = connection.prepareStatement(sql); //设置游标读取参数 prepareStatement.setFetchSize(1); //执行查询语句,返回结果集 rs = prepareStatement.executeQuery(); //取结果集 while(rs.next()) { System.out.println(rs.getString(1)); } //此时的执行结果的按照设置的参数进行结果的操做,一条条地处理 } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { try { if (null != connection) connection.close(); if (null != rs) rs.close(); if (null != prepareStatement) prepareStatement.close(); } catch (SQLException e) { e.printStackTrace(); } } } }
读取的每一条记录中包含大字段的内容,在实际开发过程当中,为了方便管理,每每数据记录会包含大字段的内容,读取可能会出现内存溢出。
处理方式:流方式读取
jdbc的实现:
rs = prepareStatement.executeQuery(); //取结果集 while(rs.next()) { System.out.println(rs.getString(1)); InputStream in = rs.getBinaryStream(1); File file = new File(File_URL); OutputStream out = null; out = new FileOutputStream(file); int temp = 0; while ((temp = in.read()) != -1) { out.write(temp); } in.close(); out.close(); }
海量的数据插入,若是一条条的插入,每一次的sql语句的发送与接收都须要时间
更加高效的使用方式为
批处理:
发送一次sql 插入多条语句
Statement提供了三个接口:
addbatch()
executeBatch()
clearBatch()
遍历须要插入的元素,将其放入batch中,而后执行executeBatch最后执行clearBatch()。
Set<String> users = new HashSet<String>(); String user1 = "zhangsan"; String user2 = "lisi"; String user3 = "zhaowu"; users.add(user1); users.add(user2); users.add(user3); Statement statement = connection.createStatement(); String sql2 = "insert into tableName(user)values("; for (String user : users) { statement.addBatch(sql + user + ")"); } statement.executeBatch(); statement.clearBatch();
涉及到中文,须要注意可能出现的乱码问题
能够设置不一样级别的代码:server级别,database级别,table级别, 字段级别,
优先级依次增大,好比设置列级别的编码,那么其余三个就不会生效。
咱们须要设置jdbc的编码方式来适应数据库的编码方式,设置方式也很简单,须要在url中增长
例如 : url = url +"characterEncoding=utf8";