JDBC学习总结
01JDBC-更新数据
02JDBC-查询数据
03JDBC-DBUtil
04JDBC-事务
05JDBC-事务锁
06JDBC-SQL注入攻击
1 01JDBC-更新数据 2 A、加载驱动 3 Class.forName("com.mysql.jdbc.Driver"); 4 B、获取数据库链接 5 Connection connection = DBUtil.getConnect(); 6 C、创建sql容器,加载sql语句 7 String sql = "insert into t_user(id,name) values(?,?,?)"; 8 PreparedStatement prepareStatement = connection.prepareStatement(sql); 9 D、填充sql语句中的问号 10 prepareStatement.setLong(1,user.getId()); 11 prepareStatement.setString(2,user.getName()); 12 E、执行sql语句 13 prepareStatement.executeUpdate(); 14 G、提交事务 15 connection.commit; 16 H、关闭数据库资源 17 DBUtil.close(prepareStatement, connection); 18 /* 19 1、B中出现的DBUtil值一个数据库链接的工具包 20 2、C中只是一个具体的例子,并不是只局限于插入操作 21 3、D中setLong中的Long是基本数据类型,它是由该方法的第二个参数类型确定 22 - 参数1表表示第几个问号 23 - 参数2表示向问号中输入的具体数据24 */
1 02JDBC-查询数据 2 A、加载驱动 3 Class.forName("com.mysql.jdbc.Driver"); 4 B、获取数据库链接 5 Connection connection = DBUtil.getConnect(); 6 C、创建sql容器,加载sql语句 7 String sql = "select * from t_user where id=?"; 8 PreparedStatement prepareStatement = connection.prepareStatement(sql); 9 D、填充sql语句中的问号 10 prepareStatement.setLong(1,id); 11 E、执行sql语句 12 ResultSet resultSet = prepareStatement.executeQuery(); 13 G、处理查询结果 14 while(resultSet.next()){ 15 resultSet.getInt("id"); 16 resultSet.getString("name"); 17 } 18 G、提交事务 19 connection.commit; 20 H、关闭数据库资源 21 DBUtil.close(prepareStatement, connection);
1 03JDBC-DBUtil 2 public class DBUtil { 3 private static final String URL = "jdbc:mysql://127.0.0.1:3306/test2"; 4 private static final String user = "root"; 5 private static final String passwd = "root"; 6 7 //1 加载驱动 8 static { 9 try { 10 Class.forName("com.mysql.jdbc.Driver"); 11 } catch (ClassNotFoundException e) { 12 e.printStackTrace(); 13 } 14 } 15 16 //2 获取数据库链接 17 public static Connection getConnect(){ 18 Connection connection = null; 19 try { 20 connection = DriverManager.getConnection(URL,user,passwd); 21 connection.setAutoCommit(false); //设置为手动提交事务 22 } catch (SQLException throwables) { 23 throwables.printStackTrace(); 24 } 25 return connection; 26 } 27 28 //3 关闭数据库资源 29 public static void close(PreparedStatement preparedStatement, Connection connection){ 30 DBUtil.close(null,preparedStatement,connection); 31 } 32 33 public static void close(ResultSet resultSet, PreparedStatement preparedStatement, Connection connection){ 34 if (resultSet != null) 35 { 36 try { 37 resultSet.close(); 38 } catch (SQLException throwables) { 39 throwables.printStackTrace(); 40 } 41 } 42 if (preparedStatement != null) 43 { 44 try { 45 preparedStatement.close(); 46 } catch (SQLException throwables) { 47 throwables.printStackTrace(); 48 } 49 } 50 if (connection != null) 51 { 52 try { 53 connection.close(); 54 } catch (SQLException throwables) { 55 throwables.printStackTrace(); 56 } 57 } 58 } 59 }
1 04JDBC-事务 2 3 如果 connection 调用方法 setAutoCommit 并设置为手动提交 4 connectio.setAutoCommit(false); //true 为自动 false 为手动 5 6 那么在sql语句执行处理之后,必须提交事务 7 connection.commit(); 8 或者出现异常会滚事务: 9 connection.rollback();
1 05JDBC-事务锁 2 3 4 事务锁: 5 6 当数据库执行修改语句时,会默认添加一个事务锁, 7 如果我们的修改条件是索引字段,那么数据库会添加一个行级锁, 【目前索引字段就认为是主键和外键】 8 如果修改的条件不是索引,那么数据库会添加一个表级锁 9 行级锁会锁住被修改的记录,不允许其他的线程(事务),在当前事务提交或回滚之前来对数据进行修改 10 表级锁会锁柱当前表中所有的记录,不允许其他的线程(事务),在当前事务提交或回滚之前来对数据进行修改 11 12 因此修改数据时尽量使用主键作为唯一的条件 13 14 数据库不仅可以使用update添加锁,也可以使用查询语句添加锁 15 select * from 表名 where ... for update 16 在普通的查询语句中添加for update就可以为语句添加一个锁 17 如果查询语句的where条件使用索引那么就是行级锁 18 如果查询语句的where条件使用的是普通的字段,那么就是一个表级锁 19 20 注意:无论是update还是select语句添加的锁,锁的释放时机以及加锁的时机都是一样的 21 22 加锁的时机是,在执行sql语句时直接加锁 23 释放锁的时机,在事务提交或回滚以后才会释放锁 24 25 例如:在数据库中操作 26 27 行级锁: 28 29 A控制台 30 start transaction; //打开事务机制 31 update t_user set name='lisi' where id=22; 32 33 B控制台 34 update t_user set name='王五' where id=22; 35 36 总结:因为id是主键,所以A控制台执行sql语句,并且没有提交事务(commit;) 37 那么id=22那一行记录就被锁定成行级锁 38 所以B控制台修改该条记录失败 39 40 表级锁: 41 42 A控制台 43 start transaction; //打开事务机制 44 update t_user set name='lisi' where user_name='root'; 45 46 B控制台 47 update t_user set name='王五' where id=22; 48 update t_user set name='王五' where id=23; 49 50 51 总结:因为user_name不是主键,也不是索引项,所以A控制台执行sql语句,并且没有提交事务(commit;) 52 那么此时该表被锁定成表级锁 53 所以B控制台无法修改表中任何记录
1 06JDBC-SQL注入攻击 2 3 PreparedStatement 是预编译的,语句中使用?作占位符,需要后期单独动态的为?赋值, 4 由于使用的是预编译,因此SQL语句指挥预编译一次 5 然后动态为?赋值即可,它的速度快,而且可以避免SQL注入攻击 6 7 Statement 是字符拼接的,所有的语句参数都需要使用字符拼接的方式拼接到SQL中,因此每次编译的SQL都不一样, 8 所以每次执行SQL语句都需要编译 9 它的速度慢,而且容易导致SQL的注入攻击 10