SQL注入及PreparedStatement 事务 三大范式 mysqldump备份

?SQL注入

SQL注入问题:是指通过客户输入到后台的那些能到数据库得到数据的位置上,恶性的输入一些 对数据有害的操作。
  首先看一个案例

        Scanner sc = new Scanner(System.in);
        System.out.println("输入你所要查询的id");
        String i = sc.nextLine();
        String sql = "select id,name,password,email from users where id = "+ i;
        Statement statement = connection.createStatement();
        ResultSet resultSet = statement.executeQuery(sql);

        while(resultSet.next()){
            System.out.println(resultSet.getObject("id"));
            System.out.println(resultSet.getObject("name"));
            System.out.println(resultSet.getObject("password"));
            System.out.println(resultSet.getObject("email"));
        }

  通过键盘输入id值来查询相应用户的名字、密码、邮箱等相关信息
  正常情况输入对应id便可查出对应信心
  但是对于这个代码,如果你输入1 or true便可获取到所有用户的信息

输入你所要查询的id
1 or true
1
zhansan
123456
zs@sina.com
2
lisi
123456
lisi@sina.com
3
wangwu
123456
wangwu@sina.com

  同样,如果用类似代码写的登录程序,只要我们输入 随意字符 or true,运行到or的时候已经是条件成立,所以无论后面是否正确,无需验证密码即可登陆成功。
  上面的问题都是通过在SQL语句中添加特殊的字符,构成关键字,改变了程序运行轨迹,从而对数据进行操作

? PrepareddStatement

  PrepareStatement是Statement的子类,它的实例对象可以用过调用  Connection.preparedStatement()方法获得,相对于Statement对象,PrepareStatement可以避免SQL注入的问题
  Statement会使数据库频繁编译SQL,可能造成数据库缓冲区溢出。PreparedStatement可对 SQL进行预编译,从而提高数据库的执行效率。并且PreperedStatement对于sql中的参数, 允许使用占位符的形式进行替换,简化sql语句的编写。
PrepareStatement与Statement的异同:
  相同点 : 都是用来执行sql语句的
  不同点
  Statement: 不安全,不能预编译SQL,不能使用占位符 ,容易造成SQL语句拼接错误
  preparedStatement :安全,预编译SQL语句,可以使用?占位符,SQL更清晰。

		Scanner sc = new Scanner(System.in);
        System.out.println("输入你所要查询的id");
        int i = sc.nextInt();
        System.out.println("输入你要查询的姓名");
        sc = new Scanner(System.in);
        String name = sc.nextLine();
        String sql = "select id,name,password,email from users where id = ? and name = ? ";
        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        preparedStatement.setInt(1,i);
        preparedStatement.setString(2,name);
        ResultSet resultSet = preparedStatement.executeQuery();
        while(resultSet.next()){
            System.out.println(resultSet.getObject("id"));
            System.out.println(resultSet.getObject("name"));
            System.out.println(resultSet.getObject("password"));
            System.out.println(resultSet.getObject("email"));
        }
        connection.close();
        preparedStatement.close();
        resultSet.close();

?事务

  每条sql语句都是一个事务   事务只对DML语句有效,对DQL语句无效
  假设操作有4个步骤,如果四个步骤全部都完成,则认为事务成功,如果四个步骤中有任意一个步骤失败,则认为事务失败

  事务的四大特性(ACID)
  (1)原子性 Atomicity
  事务包含的所有操作,要么全部成功,要么全部失败回滚。
  (2)一致性 Consistency
  一致性是指事务必须使数据库从一个一致性状态转换到另外一个一致性状态,也就是说一个事务必须使数据库执行之前和执行之后都处于一致性状态。让数据保持一定的合理性。比如说一个商品售出时,仓库数量减一,订单里数量加一
  (3)隔离性 Isolation
  隔离性是指当多个用户访问数据库时,数据库为每一个用户开启的事务不能被其他事务的操作所干扰,多个并发事务直接要相互隔离,不互相影响。
  (4)持久性 Durability
  事务一旦提交,就没有办法更改,被永久的记录在数据库中。
  
  1、事务的开启
  start transaction事务的开启具有隔离性,也就是当事务还没有提交的时候,其他用户访问到的数据库的数据没有发生改变
  2、事务数据的提交
  commit当事务提交了之后,里面的数据就发生了改变,此时其他用户访问数据库的时候,就是访问到被改变的数据库的数据了。
  3、事务的回滚
  rollback比如在超市商品的商品售出中分为两步,仓库中的商品数量减少,订单中的商品数量增加,但如果当仓库中数量减少之后,系统发生了意外如断电等导致订单的商品没有加上,那么此时rollback,事务回滚,仓库中的商品数量又加回来了。
  注意:一般情况下commit和rollback只出现其一
  4、事务的并发操作
  脏读: 又称无效数据的读出,是指在数据库访问中,事务T1将某一值修改,然后事务T2读取该值,此后T1因为某种原因撤销对该值的修改,这就导致了T2所读取到的数据是无效的。脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是脏数据,依据脏数据所做的操作可能是不正确的。
  不可重复读: 在一个事务内,多次读同一个数据。在这个事务还没有结束时,另一个事务也访问该同一数据并修改数据。那么,在第一个事务的两次读数据之间。由于另一个事务的修改,那么第一个事务两次读到的数据可能不一样,这样就发生了在一个事务内两次读到的数据是不一样的,因此称为不可重复读,即原始读取不可重复。
  6、事务的隔离级别
  (1)Read uncommitted 一个事务可以读取到另一个未提交的事务
  (2)Read commit 一个事务只能读取到另一个事务提交的结果
  (3)Repeatable read 当一个事务在执行时,不允许其他事务来抢占资源
  (4)Serializable 序列化,实现多个访问共享数据的事务得以线性顺序进行
  查看隔离级别:select @@global.tx_isolation,@@tx_isolation;
  设置隔离级别:set global transaction isolation level read committed;

用JDBC对事务进行测试
public class Test1 {
    public static void main(String[] args) throws Exception {
        Class.forName("com.mysql.jdbc.Driver");
        String url = "jdbc:mysql://localhost:3306/myschool";
        String user = "root";
        String password = "123456";
        Connection co = DriverManager.getConnection(url, user, password);
        co.setAutoCommit(false);//关闭数据库的自动提交,通知数据库开启事务控制
        String sql = "delete from student where id = 1";
        Statement statement = co.createStatement();
        statement.executeUpdate(sql);
        co.rollback();//删除之后的回滚
    }
}

代码执行前在这里插入图片描述
代码执行后,并没有变化在这里插入图片描述
将上面代码的co.rollback();换成co.commit();事务提交,删除成功
在这里插入图片描述

?三大范式

第一范式(1NF)(无重复的列)
在任何一个关系数据库中,第一范式(1NF)是对关系模式的基本要求,不满足第一范式(1NF)的数据库就不是关系数据库。
所谓第一范式(1NF)是指数据库表的每一列都是不可分割的基本数据项,同一列中不能有多个值,即实体中的某个属性不能有多个值或者不能有重复的属性。如果出现重复的属性,就可能需要定义一个新的实体,新的实体由重复的属性构成,新实体与原实体之间为一对多关系。在第一范式(1NF)中表的每一行只包含一个实例的信息。简而言之,第一范式就是无重复的列。

第二范式(2NF)(唯一属性列被称为主关键字或主键、主码)
第二范式(2NF)是在第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)必须先满足第一范式(1NF)。第二范式(2NF)要求数据库表中的每个实例或行必须可以被唯一地区分。为实现区分通常需要为表加上一个列,以存储各个实例的唯一标识。这个唯一属性列被称为主关键字或主键、主码。
第二范式(2NF)要求实体的属性完全依赖于主关键字。所谓完全依赖是指不能存在仅依赖主关键字一部分的属性,如果存在,那么这个属性和主关键字的这一部分应该分离出来形成一个新的实体,新实体与原实体之间是一对多的关系。为实现区分通常需要为表加上一个列,以存储各个实例的唯一标识。简而言之,第二范式就是非主属性非部分依赖于主关键字。

第三范式(3NF)(属性不依赖于其它非主属性)
满足第三范式(3NF)必须先满足第二范式(2NF)。简而言之,第三范式(3NF)要求一个数据库表中不包含已在其它表中已包含的非主关键字信息。第三范式就是属性不依赖于其它非主属性。

?mysqldump备份

1、导出一张表
格式:mysqldump -u用户名 -p密码 database 表名 >路径 .sql
例如:mysqldump -uroot -p123456 jdbcstudy users > d:/a.sql;
2、导处两张表
格式:mysqldump -uroot -ppassword database table1 table2 table3 > .sql
例如:mysqldump -uroot -p123456 jdbcstudy users1 users2 users3 > d:/a.sql;
3、导出所有表
格式:mysqldump -uroot -ppassword database > .sql
例如:mysqldump -uroot -p123456 jdbcstudy > d:/.sql
4、导出一个库
格式:mysqldump -uroot -ppassword -B database > .sql
例如:mysqldump -uroot -p123456 -B jdbcstudy > .sql

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值