Java JDBC连接数据库的CURD操作(JDK1.8 + MySQL8.0.33 + mysql-connector-java-8.0.27-bin驱动)
JDBC概述
-
-
JDBC为访问不同的数据库提供了一种统一的途径,为开发者屏蔽了一些细节问题。
-
JDBC的目标是使Java程序员使用JDBC可以连接任何提供了JDBC驱动程序
Class.forName(“com.mysql.cj.jdbc.Driver”);
注意:驱动版本8+以上的才需要在jdbc前面.cj,否则直接写“com.mysql.jdbc.Driver”
2、获取连接
使用DriverManager.getConnection(url,user,password);获取连接
-
-
jdbc:mysql://主机名称:mysql服务端口号/数据库名称?参数=值&参数=值
-
jdbc:mysql://localhost:3306/数据库名
-
jdbc:mysql://localhost:3306/数据库名?useUnicode=true&characterEncoding=utf8(如果JDBC程序与服务器端的字符集不一致,会导致乱码,那么可以通过参数指定服务器端的字符集)
-
连接数据库的时候也可以使用配置文件的方式保存配置信息,在代码中加载配置文件,这里就不再赘述。
为什么要用
问题一:存在拼串操作,繁琐
问题二:存在SQL注入问题
-
SQL 注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的 SQL 语句段或命令(如:SELECT user, password FROM user_table WHERE user='a' OR 1 = ' AND password = ' OR '1' = '1') ,从而利用系统的 SQL 引擎完成恶意行为的做法。
-
-
-
PreparedStatement 接口是 Statement 的子接口,它表示一条预编译过的 SQL 语句
-
1 Class.forName("com.mysql.cj.jdbc.Driver"); 2 3 Connection connection = DriverManager.getConnection(URL, name, password); 4 5 String sql = "SELECT * FROM t_user;"; 6 7 PreparedStatement preparedStatement = connection.prepareStatement(sql); 8 9 ResultSet resultSet = preparedStatement.executeQuery(); 10 11 while (resultSet.next()){ 12 int id = resultSet.getInt("id"); 13 String account = resultSet.getString("account"); 14 String pw = resultSet.getString("PASSWORD"); 15 String nickname = resultSet.getString("nickname"); 16 17 System.out.println(id+"\t"+account+"\t"+pw+"\t"+nickname); 18 } 19 20 resultSet.close(); 21 22 preparedStatement.close(); 23 24 connection.close();
如果要传入参数,首先在sql语句中用?去占位,再调用setObject方法传递参数,如下所示:
1 Class.forName("com.mysql.cj.jdbc.Driver"); 2 3 Connection connection = DriverManager.getConnection(url, name, password); 4 5 String sql = "SELECT * FROM t_user WHERE account=? AND password=?;"; 6 7 PreparedStatement preparedStatement = connection.prepareStatement(sql); 8 9 String account = "root"; 10 String pw = "123456"; 11 12 preparedStatement.setObject(1,account); 13 14 preparedStatement.setObject(2,pw); 15 16 ResultSet resultSet = preparedStatement.executeQuery(); 17 18 boolean next = resultSet.next(); 19 System.out.println(next); 20 21 resultSet.close(); 22 23 preparedStatement.close(); 24 25 connection.close();
ResultSet
-
-
ResultSet 对象以逻辑表格的形式封装了执行数据库操作的结果集,ResultSet 接口由数据库厂商提供实现
-
ResultSet 返回的实际上就是一张数据表。有一个指针指向数据表的第一条记录的前面。
-
ResultSet 对象维护了一个指向当前数据行的游标,初始的时候,游标在第一行之前,可以通过 ResultSet 对象的 next() 方法移动到下一行。调用 next()方法检测下一行是否有效。若有效,该方法返回 true,且指针下移。相当于Iterator对象的 hasNext() 和 next() 方法的结合体。
-
当指针指向一行时, 可以通过调用 getXxx(int index) 或 getXxx(int columnName) 获取每一列的值。
-
例如: getInt(1), getString("name")
-
-
资源的释放
-
-
数据库连接(Connection)是非常稀有的资源,用完后必须马上释放,如果Connection不能及时正确的关闭将导致系统宕机。Connection的使用原则是尽量晚创建,尽量早的释放。
-
-
可用于获取关于 ResultSet 对象中列的类型和属性信息的对象
-
ResultSetMetaData meta = rs.getMetaData();
-
getColumnName(int column):获取指定列的名称
-
getColumnLabel(int column):获取指定列的别名
-
getColumnCount():返回当前 ResultSet 对象中的列数。
-
getColumnTypeName(int column):检索指定列的数据库特定的类型名称。
-
getColumnDisplaySize(int column):指示指定列的最大标准宽度,以字符为单位。
-
isNullable(int column):指示指定列中的值是否可以为 null。
-
-
1 Class.forName("com.mysql.cj.jdbc.Driver"); 2 3 Connection connection = DriverManager.getConnection(url, name, password); 4 5 6 String sql = "SELECT id as ID,account as 账号,password as 密码,nickname as 昵称 FROM t_user;"; 7 8 PreparedStatement preparedStatement = connection.prepareStatement(sql); 9 10 ResultSet resultSet = preparedStatement.executeQuery(); 11 12 ResultSetMetaData metaData = resultSet.getMetaData(); 13 14 List<Map> res = new ArrayList<>(); 15 16 while (resultSet.next()){ 17 Map map = new HashMap(); 18 19 int columnCount = metaData.getColumnCount(); 20 21 for (int i = 1; i <= columnCount; i++) { 22 String columnName = metaData.getColumnLabel(i); 23 map.put(columnName,resultSet.getObject(i)); 24 } 25 26 res.add(map); 27 } 28 29 for (Map re : res) { 30 System.out.println(re); 31 } 32 33 resultSet.close(); 34 35 preparedStatement.close(); 36 37 connection.close();
主键回显
利用getGeneratedKeys方法获取一个结果集,首先在connection.prepareStatement方法中再传入一个参数:Statement.RETURN_GENERATED_KEYS 也可以用1代替(不推荐)
1 Class.forName("com.mysql.cj.jdbc.Driver"); 2 3 Connection connection = DriverManager.getConnection(url, name, password); 4 5 String sql = "INSERT INTO t_user(account,password,nickname) VALUES(?,?,?);"; 6 7 PreparedStatement preparedStatement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS); 8 9 preparedStatement.setObject(1,"test01"); 10 preparedStatement.setObject(2,"123456"); 11 preparedStatement.setObject(3,"JDBC"); 12 13 int i = preparedStatement.executeUpdate(); 14 15 if (i!=0){ 16 System.out.println("Success"); 17 ResultSet generatedKeys = preparedStatement.getGeneratedKeys(); 18 generatedKeys.next(); 19 int anInt = generatedKeys.getInt(1); 20 System.out.println("主键="+anInt); 21 }else { 22 System.out.println("False"); 23 } 24 25 preparedStatement.close(); 26 27 connection.close();
JDBC的批量处理语句包括下面三个方法:
-
-
addBatch(String):添加需要批量处理的SQL语句或是参数;
-
executeBatch():执行批量处理语句;
-
clearBatch():清空缓存的数据
-
通常我们会遇到两种批量执行SQL语句的情况:
-
-
多条SQL语句的批量处理;
-
-
注意:mysql服务器默认是关闭批处理的,我们需要通过一个参数,让mysql开启批处理的支持。
String url = "jdbc:mysql://localhost:3306/databasename?rewriteBatchedStatements=true";写在配置文件的url后面
用preparedStatement.addBatch();将数据添加到sql语句后面
注意:写sql语句的时候后面不能写分号!
最后添加完了用
preparedStatement.executeBatch();执行sql语句,示例如下:
1 String url = "jdbc:mysql://localhost:3306/databasename?rewriteBatchedStatements=true"; 2 3 Class.forName("com.mysql.cj.jdbc.Driver"); 4 5 Connection connection = DriverManager.getConnection(url, name, password); 6 7 String sql = "INSERT INTO t_user(account,password,nickname) VALUES(?,?,?)"; 8 9 PreparedStatement preparedStatement = connection.prepareStatement(sql); 10 11 for (int i = 0; i < 10000; i++) { 12 preparedStatement.setObject(1,"test"+i); 13 preparedStatement.setObject(2,"password"+i); 14 preparedStatement.setObject(3,"tt"+i); 15 16 preparedStatement.addBatch(); 17 } 18 19 preparedStatement.executeBatch(); 20 21 preparedStatement.close(); 22 23 connection.close();