【MySql】数据库操作对象详解

【MySql】数据库操作对象详解

数据库的操作对象有三种,PreparedStatement可以有效防止Sql注入问题,常用

Statement操作数据库的CRUD(增删改查)
PreparedStatement操作数据库的CRUD(增删改查)
CallableStatement操作数据库的存储过程
  • 3.1、Statement

    弊端:我们如果编写带条件的sql语句需要拼凑,并且存在sql注入的问题

    下面是控制台模拟的一个登陆系统,在其中sql语句的拼凑很容易出错

    @Test
    	public void test() throws Exception {
    		/**
    		 * 模拟登陆功能:登陆就是去验证后台的用户名和密码
    		 * 分析:
    		 * 	  创建用户时输入的用户名和密码:插入语句到数据库保存起来。(insert)
    		 * 	  登陆:查询登陆时输入的用户名和密码是否与创建时的一样	(select)
    		 */
    		
    		// 模拟前端发送到后台的内容
    		Scanner sc = new Scanner(System.in);
    		System.out.println("请输入您的用户名:");
    		String userName = sc.nextLine();
    		System.out.println("请输入您的密码:");
    		String pwd = sc.nextLine();
    		
    		// 去验证用户,是否通过
    		// 连接数据库
    		InputStream config =   JdbcTest.class.getClassLoader().getResourceAsStream("resources/config.properties");
    		Properties prop = new Properties();	
    		prop.load(config);
    		String driver = prop.getProperty("driver");
    		String url = prop.getProperty("url");
    		String user = prop.getProperty("user");
    		String password = prop.getProperty("password");
    		// 加载驱动
    		Class.forName(driver);
    		// 获得数据库连接对象
    		Connection connection = DriverManager.getConnection(url,user,password);
    		// 获得数据库操作对象
    		Statement statement = connection.createStatement();
    		
    		// sql查询语句,查询数据库中是否有此用户
    		String sql = "select * from login where userName= '"+userName+"'and   password='"+pwd+"'";
    		
    		// 提交sql语句,得到返回的结果
    		ResultSet res = statement.executeQuery(sql);
    		
    		/* 判断结果
    		   1.直接判断res.next()
    		   2.把结果封装成java对象,判断对象是否为null
    		 */
    		
        // next判断当前行有没有数据,所以下面就是当前行如果查到数据,则登陆成功
    		if(res.next()) {
    			System.out.println("登陆成功!");
    		} else {
    			System.out.println("用户名或密码错误");
    		}
      }
    

    SQL注入问题:sql语句的随意添加

    在上面的登陆系统中,如果用户输入了密码为 ' or 1 = '1,则会形成恒成立

    // 原本的sql查询语句是这样,如果加入了`' or 1 = '1`,就变成了恒成立
    "select * from login where userName= '"+userName+"'and   password='"+pwd+"'";
    // 加入`' or 1 = '1`,这样就对我们的sql语句进行变化,所以无论用户名是什么可以获取所有的信息
    "select * from login where userName= '"+userName+"'and   password='' or 1='1'";
    
    
  • 3.2、PreparedStatement
    • PreparedStatement执行sql语句和Statement执行方法一样,不同的是,Statement是在执行的时候需要提交sql语句就可以,但PreparedStatement在创建时就需要sql语句的格式进行预编译,从而保证了sql注入问题不会出现,也解决了Statement的拼接sql语句的问题

    • 在预编期间,sql语句中的值可以使用?代替,来把位置占着

      String sql = "insert into student(s_id,s_name) values(?,?)"; // ?:占位符
      PreparedStatement prepareStatement = connection.prepareStatement(sql);
      
    • 在执行之前,需要把内容填充进占位符占了的位置,为此PreparedStatement提供了set系列方法

      // 第一个参数表示当前设置的第几个占位符,第二个参数表示当前占位符的值
      prepareStatement.setInt(1, 555);     
      prepareStatement.setString(2, "小明");
      
    • 执行的时候直接使用提交就可以

      // 此时的提交方式中不用带任何参数,返回类型和Statement一样
      int res = prepareStatement.executeUpdate();
      
    • 为什么PreparedStatement操作对象可以防止sql注入问题

      因为我们在创建PreparedStatement之前,sql语句已经预编过了,相当于刚开始编译前只有and的话,后面不管输入什么都是以字符串形式了,不会有其他的逻辑连接。

    • PreparedStatement还可以操作二进制数据,而Statement不能

      注意:虽然PreparedStatement可以存储二进制文件,但是一般不会把文件存储到数据库,如果要传输大文件,需要修改mysql配置,允许最大保存为16Mmax_allowed_packet=16M

      插入二进制文件:
      // 预编译sql
      String sql = "insert into student(s_name,s_image) values(?,?)";
      // 创建PreparedStatement对象
      PreparedStatement prepareStatement = connection.prepareStatement(sql);
      // 添加数据,解释?占位符
      prepareStatement.setString(1, "宁荣荣");
      // 通过setBlob的方法可以把文件二进制的存放到数据库
      prepareStatement.setBlob (2,new FileInputStream("src/resources/1.jpg"));
      // 提交操作	
      int res = prepareStatement.executeUpdate();
      
      读取二进制文件:
      // 预编译sql
      String sql = "select s_image from student where s_name=?";
      // 创建PreparedStatement对象
      PreparedStatement prepareStatement = connection.prepareStatement(sql);
      // 添加数据,解释?占位符
      prepareStatement.setString(1, "宁荣荣");
      // 提交操作,返回结果集合	
      ResultSet res = prepareStatement.executeQuery();
      // 判断结果集
      		while(res.next()) {
      			// 获取图片的二进制数据
      			Blob blob = res.getBlob("s_image");
      			// 将二进制数据读取到内存
      			InputStream binaryStream = blob.getBinaryStream();
      			// 将内存中的二进制文件通过io写出到磁盘
      			FileOutputStream fos = new FileOutputStream("src/resources/2.jpg");
      			// io流写文件
      			byte[] buffer = new byte[1024];
      			int len;
      			while((len=binaryStream.read(buffer))!=-1) {
      				fos.write(buffer,0,len);
      			}
         // 关闭流
      			fos.close();
         binaryStream.close();
      		}
      

sql提交详解

Sql的提交基本上有三种方式,其中execute不常用

方式返回值详解
executeQuery查询结果集合做查询语句时用此方式提交,可以返回查询到的结果,遍历集合则可以获得数据
executeUpdate操作受影响的行数做增删改操作时用此方式提交,返回操作受影响的行数,判断返回值大于1,说明操作成功,不然则是操作失败
executeboolean值操作的方式所有的sql都可以用此方式提交,返回true,说明做了查询操作,返回false说明做了增删改操作
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值