JDBC是通过Class.forName(String)
反射加载所需的驱动类。然后就可以通过jdk自带的DriverManager
的静态方法获取一个数据库连接:Connection
。通过这个Connection我们就可以对数据库进行增删查改了。要对数据库进行增删查改还是离不开sql。需要使用sql,调用Connection的方法创建一个Statement
或者PreparedStatement
对象。创建Statement就利用一句完整的sql就好了,但是不防止注入。而PreparedStatement的sql在参数上用问号代替,作为占位符。之后再填充这些占位符,其占位符是用下标指定,下标从1开始,是防止注入的。创建好PreparedStatement执行。在这里可以设置事务。如果是select,执行后返回一个ResultSet
对象作为返回结果。可以通过这个结果获取列名,元组的数据等。如果是insert,delete或者update,会返回一个int,表示受此命令影响的行数。
JDBC的优化
Connection对象是线程不安全的,要不然就不会有说一个请求创建一个Connection对象,就不需要数据库连接池了。
一直有个误区,其实数据库连接池是JDBC的一直优化手段,而不是两种方法。哪怕是使用了数据库连接池,使用JDBC的话也是直接操作connect和PreparedStatement的。当操作量大的时候,数据库连接池就有连接数控制,防止连接泄露等功能。但是如果操作量很少的话,就会有大量连接在数据库连接池里闲置了。
对大量相同的sql操作使用批处理,在一次交互里处理大量的操作,而不是每个操作进行一次交互。批处理例子如下,能有效提高操作速度。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
| package jdbc;
import java.sql.*; import java.util.Arrays; import java.util.HashMap; import java.util.Map;
public class Jdbc { public static void main(String[] args) throws ClassNotFoundException, SQLException { main(); }
public static final void main() throws ClassNotFoundException, SQLException { Class.forName("com.mysql.jdbc.Driver"); String url = "jdbc:mysql://127.0.0.1:3306/mysql?useSSL=false"; Connection connection = DriverManager.getConnection(url, "root", "pass");
connection.setAutoCommit(false); String sql = "select * from engine_cost"; Object[] objects = new Object[]{}; PreparedStatement preparedStatement = connection.prepareStatement(sql); for (int i = 0; i < objects.length; i++) { preparedStatement.setObject(i + 1, objects[i]); }
try (PreparedStatement ps = preparedStatement; ResultSet resultSet = preparedStatement.executeQuery()) { ResultSetMetaData resultSetMetaData = resultSet.getMetaData(); String[] columnLabels = new String[resultSetMetaData.getColumnCount()]; for (int i = 0; i < columnLabels.length; i++) { columnLabels[i] = resultSetMetaData.getColumnLabel(i + 1); }
resultSet.last(); Map<String, Object>[] maps = new Map[resultSet.getRow()]; resultSet.beforeFirst(); int i = 0; while (resultSet.next()) { maps[i] = new HashMap<String, Object>(); for (String columnName : columnLabels) { maps[i].put(columnName, resultSet.getObject(columnName)); } i++; }
for (Map<String, Object> map : maps) { System.out.println(map); }
connection.commit(); } catch (Exception e) { connection.rollback(); e.printStackTrace(); } }
public static final void main(Connection connection) throws SQLException { connection.setAutoCommit(false); String sql = "insert into tableName(id) values(?)"; Object[] objects = new Object[]{"id"}; PreparedStatement preparedStatement = connection.prepareStatement(sql);
try (PreparedStatement ps = preparedStatement) { for (int i = 0; i < 10000; i++) { for (int j = 0; j < objects.length; j++) { preparedStatement.setObject(j + 1, objects[j]); } preparedStatement.addBatch();
if (i % 1000 == 0) { int[] lens = preparedStatement.executeBatch(); System.out.println("批处理影响的行(?): "+Arrays.toString(lens)); connection.commit(); preparedStatement.clearBatch(); } }
connection.commit(); } catch (Exception e) { connection.rollback(); e.printStackTrace(); } } }
|
参考文章:
JDBC中Connection解惑
用Java向数据库中插入大量数据时的优化