SQL注入
什么是SQL注入
所谓 SQL 注入,就是通过把含有 SQL 语句片段的参数插入到需要 执行的 SQL 语句中, 最终达到欺骗数据库服务器执行恶意操作的 SQL 命令。
SQL注入案例
/** * SQL注入测试类 */ public class SqlInjectTest { /** * 体现sql注入 */ public void sqlInject(String username,int userage){ Connection connection =null; Statement statement =null; ResultSet resultSet =null; try{ //获取连接 connection = JdbcUtils.getConnection(); //创建Statement对象 statement = connection.createStatement(); //定义sql语句 String sql ="select * from users where username ='"+username+"' and userage = "+userage; System.out.println(sql); //执行sql语句 resultSet = statement.executeQuery(sql); //处理结果集 while(resultSet.next()){ int userid = resultSet.getInt("userid"); String name = resultSet.getString("username"); int age = resultSet.getInt("userage"); System.out.println(userid+" "+name+" "+age); } }catch(Exception e){ e.printStackTrace(); }finally{ JdbcUtils.closeResource(resultSet,statement,connection); } } public static void main(String[] args) { SqlInjectTest sit = new SqlInjectTest(); sit.sqlInject("oldlu' or 1=1 --",28); } }
解决SQL注入
public void noSqlInject(String username,int userage){ Connection connection = null; PreparedStatement ps =null; ResultSet resultSet = null; try{ //获取连接 connection = JdbcUtils.getConnection(); //创建PreparedStatement对象 ps = connection.prepareStatement("select * from users where username = ? and userage = ?"); //绑定参数 ps.setString(1,username); ps.setInt(2,userage); //执行sql resultSet = ps.executeQuery(); //处理结果集 while(resultSet.next()){ int userid = resultSet.getInt("userid"); String name = resultSet.getString("username"); int age = resultSet.getInt("userage"); System.out.println(userid+" "+name+" "+age); } }catch(Exception e){ e.printStackTrace(); }finally{ JdbcUtils.closeResource(resultSet,ps,connection); } }
JDBC批量添加数据
批量添加数据简介
在JDBC中通过PreparedStatement的对象的addBatch()和 executeBatch()方法进行数据的批量插入。
addBatch()把若干SQL语句装载到一起,然后一次性传送到数据库执行,即是批量处理sql数据的。
executeBatch()会将装载到一起的SQL语句执行。
注意: MySql默认情况下是不开启批处理的。 数据库驱动从5.1.13开始添加了一个对rewriteBatchStatement 的参数的处理,该参数能够让MySql开启批处理。在url中添加 该参数:rewriteBatchedStatements=true
Mysql的URL参数说明
实现数据的批量添加
在url中开启批量添加
rewriteBatchedStatements=true
实现数据的批量添加方式一
/** * 批量添加数据方式一 */ public void addBatch1(){ Connection conn = null; PreparedStatement ps =null; try{ //创建连接 conn = JdbcUtils.getConnection(); //创建PreparedStatement ps = conn.prepareStatement("insert into users values(default ,?,?)"); //参数绑定 for(int i=0;i<1000;i++){ //绑定username ps.setString(1,"ITBZ"+i); //绑定userage ps.setInt(2,20); //缓存sql ps.addBatch(); } //执行sql ps.executeBatch(); }catch(Exception e){ e.printStackTrace(); }finally{ JdbcUtils.closeResource(ps,conn); } }
实现数据的批量添加方式二
/** * 批量添加数据方式二 */ public void addBatch2(){ Connection conn = null; PreparedStatement ps =null; try{ //创建连接 conn = JdbcUtils.getConnection(); //创建PreparedStatement ps = conn.prepareStatement("insert into users values(default ,?,?)"); //参数绑定 for(int i=1;i<=1000;i++){ //绑定username ps.setString(1,"ITBZ"+i); //绑定userage ps.setInt(2,20); //缓存sql ps.addBatch(); if(i%500 == 0){ //执行sql ps.executeBatch(); //清除缓存 ps.clearBatch(); } } }catch(Exception e){ e.printStackTrace(); }finally{ JdbcUtils.closeResource(ps,conn); } }
JDBC事务处理
事务简介
事务:
事务是指作为单个逻辑工作单元执行的一系列操作,要么完全地 执行,要么完全地不执行。
事务操作流程:
1、开启事务
2、提交事务
3、回滚事务
JDBC中事务处理特点
在JDBC中,使用Connection对象来管理事务,默认为自动提交事 务。可以通过setAutoCommit(boolean autoCommit)方法设置事 务是否自动提交,参数为boolean类型,默认值为true,表示自动 提交事务,如果值为false则表示不自动提交事务,需要通过 commit方法手动提交事务或者通过rollback方法回滚事务。
JDBC事务处理实现
/** * 批量添加数据方式二 * 支持事务处理 */ public void addBatch2(){ Connection conn = null; PreparedStatement ps =null; try{ //创建连接 conn = JdbcUtils.getConnection(); //设置事务的提交方式,将自动提交修改为手动提交 conn.setAutoCommit(false); //创建PreparedStatement ps = conn.prepareStatement("insert into users values(default ,?,?)"); //参数绑定 for(int i=1;i<=1000;i++){ //绑定username ps.setString(1,"ITBZ"+i); //绑定userage ps.setInt(2,20); //缓存sql ps.addBatch(); if(i%500 == 0){ //执行sql ps.executeBatch(); //清除缓存 ps.clearBatch(); } if(i==501){ String str = null; str.length(); } } //提交事务 JdbcUtils.commit(conn); }catch(Exception e){ e.printStackTrace(); JdbcUtils.rollback(conn); }finally{ JdbcUtils.closeResource(ps,conn); } }
Blob类型的使用
MySql Blob类型简介
Blob(全称:Binary Large Object 二进制大对象)。在MySql中, Blob是一个二进制的用来存储图片,文件等数据的数据类型。操作 Blob类型的数据必须使用PreparedStatement,因为Blob类型的数 据无法使用字符串拼接。大多数情况,并不推荐直接把文件存放在 MySQL 数据库中,但如果应用场景是文件与数据高度耦合,或者对 文件安全性要求较高的,那么将文件与数据存放在一起,即安全, 又方便备份和迁移。
Mysql中的Blob类型
MySql中有四种Blob类型,它们除了在存储的最大容量上不同,其 他是一致的。
Blob类型使用的注意事项
1、实际使用中根据需要存入的数据大小定义不同的Blob类型。
2、如果存储的文件过大,数据库的性能会下降。
插入Blob类型数据
创建表
CREATE TABLE `movie` ( `movieid` int(11) NOT NULL AUTO_INCREMENT, `moviename` varchar(30) DEFAULT NULL, `poster` mediumblob, PRIMARY KEY (`movieid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
通过PreparedStatement存储Blob类型数据
/** * Blob类型操作测试类 */ public class BlobTest { /** * 向Movie表中插入数据 */ public void insertMovie(String moviename, InputStream is){ Connection conn =null; PreparedStatement ps =null; try{ //获取连接 conn = JdbcUtils.getConnection(); //创建PreparedStatement对象 ps = conn.prepareStatement("insert into movie values(default,?,?)"); //绑定参数 ps.setString(1,moviename); ps.setBlob(2,is); ps.executeUpdate(); }catch(Exception e){ e.printStackTrace(); }finally{ JdbcUtils.closeResource(ps,conn); } } public static void main(String[] args) throws FileNotFoundException { BlobTest bt = new BlobTest(); //创建读取文件的IO流 InputStream is = new FileInputStream(new File("d:/1.jpg")); bt.insertMovie("战狼",is); } }
解除文件大小限制
虽然MediumBlob允许保存最大值为16M,但MySql中默认支持的 容量为4194304即4M。我们可以通过修改Mysql的my.ini文件中 max_allowed_packet属性扩大支持的容量,修改完毕后需要重启 MySql服务。
文件位置
修改属性
读取Blob类型数据
/** * 根据影片ID查询影片信息 * @param movieid */ public void selectMovieById(int movieid) { Connection conn =null; PreparedStatement ps = null; ResultSet rs = null; try{ //获取连接 conn =JdbcUtils.getConnection(); //创建PreparedStatement对象 ps = conn.prepareStatement("select * from movie where movieid = ?"); //绑定参数 ps.setInt(1,movieid); //执行sql rs = ps.executeQuery(); while(rs.next()){ int id = rs.getInt("movieid"); String name = rs.getString("moviename"); System.out.println(id+" "+name); //获取blob类型的数据 Blob blob = rs.getBlob("poster"); //获取能够从Blob类型的列中读取数 据的IO流 InputStream is = blob.getBinaryStream(); //创建文件输出字节流对象 OutputStream os = new FileOutputStream(id+"_"+name+".jpg"); //操作流完成文件的输出处理 byte[] buff = new byte[1024]; int len; while((len = is.read(buff)) != -1){ os.write(buff,0,len); } os.flush(); is.close(); os.close(); } }catch(Exception e){ e.printStackTrace(); }finally{ JdbcUtils.closeResource(rs,ps,conn); } }
其他查询方式
模糊查询
实现模糊查询
/** * 模糊查询测试类 */ public class FuzzyQueryTest { /** * 根据用户名称模糊查找用户信息 */ public List<Users> fuzzyQuery(String username){ List<Users> list= new ArrayList<>(); Connection conn =null; PreparedStatement ps = null; ResultSet rs = null; try{ //获取数据库连接 conn = JdbcUtils.getConnection(); //创建PreparedStatement对象 ps = conn.prepareStatement("select * from users where username like ?"); //参数绑定 ps.setString(1,username); //执行sql语句 rs = ps.executeQuery(); while(rs.next()){ Users user = new Users(); user.setUserid(rs.getInt("userid")); user.setUsername(rs.getString("username")); user.setUserage(rs.getInt("userage")); list.add(user); } }catch(Exception e){ e.printStackTrace(); }finally{ JdbcUtils.closeResource(rs,ps,conn); } return list; } public static void main(String[] args) { FuzzyQueryTest ft = new FuzzyQueryTest(); List<Users> users = ft.fuzzyQuery("%d%"); for(Users user1:users){ System.out.println(user1.getUserid()+""+user1.getUsername()+" "+user1.getUserage()); } } }
动态条件查询
动态条件查询实现
/** * 动态条件查询测试类 */ public class DynamicConditionQueryTest { /** * 动态条件查询Users */ public List<Users> queryUsers(Users users){ List<Users> list= new ArrayList<>(); Connection conn =null; PreparedStatement ps = null; ResultSet rs = null; try{ //获取数据库连接 conn = JdbcUtils.getConnection(); //拼接查询SQL语句 String sql = this.generateSql(users); System.out.println(sql); //创建PreparedStatement对象 ps = conn.prepareStatement(sql); //执行sql语句 rs = ps.executeQuery(); while(rs.next()){ Users user = new Users(); user.setUserid(rs.getInt("userid")); user.setUsername(rs.getString("username")); user.setUserage(rs.getInt("userage")); list.add(user); } }catch(Exception e){ e.printStackTrace(); }finally{ JdbcUtils.closeResource(rs,ps,conn); } return list; } /** * 生成动态条件查询sql */ private String generateSql(Users users){ StringBuffer sb = new StringBuffer("select * from users where 1=1"); if(users.getUserid() > 0){ sb.append(" and userid = ").append(users.getUserid()); } if(users.getUsername() !=null &&users.getUsername().length() > 0){ sb.append(" and username = '").append(users.getUsername()).append("'"); } if(users.getUserage() > 0){ sb.append(" and userage = ").append(users.getUserage()); } return sb.toString(); } public static void main(String[] args) { DynamicConditionQueryTest dt = new DynamicConditionQueryTest(); Users users = new Users(); users.setUsername("Oldlu"); users.setUserage(20); List<Users> list = dt.queryUsers(users); for(Users user1:list){ System.out.println(user1.getUserid()+""+user1.getUsername()+" "+user1.getUserage()); } } }