2021-7-30

本文介绍了数据库的删除操作,包括删除部分记录和全部记录,以及在存在主外键约束时的注意事项。同时,详细阐述了事务的特性(ACID)、隔离级别以及Oracle的默认隔离设置。还探讨了截断数据与删除数据的区别,并展示了如何在Java中使用JDBC进行事务管理和数据库操作。最后,提到了预处理块(PreparedStatement)相对于静态处理块(Statement)的优势。
摘要由CSDN通过智能技术生成
Delete

delete [from] 表名 where 过滤行记录

说明:

  1. delete 可以删除指定部分记录,删除全部记录
  2. 记录上存在主外键关联时, 删除存在关联的主表的记录时,注意 参考外键约束, 约束强制不让删除
    先删除从表 再删除主表
--删除全部数据
delete from tb_user where 1=1;
--删除指定数据
delete from tb_user where userid<10;
--主外键关联时,注意 参考约束, 约束强制不让删除
--默认先删除从表 再删除主表
delete from tb_txt where 1=1;
delete from tb_user where 1=1;
commit;
--删除主表数据,并设置从表数据为null
--删除主表数据,级联删除从表数据
截断数据

truncate: 截断所有的数据 ,如果截断的是主表,结构不能存在外键关联,截断数据同时从结构上检查

create table emp_his as select * from emp where 1=1;
select * from emp_his;
--截断所有的数据
truncate table emp_his;
--不能截断: truncate table dept;

截断数据与删除数据区别 truncate 与delete 区别

1truncate -->ddl ,不涉及事务,就不能回滚
delete -->dml ,涉及事务,可以回滚
2truncate 截断所有的数据 delete 可以删除全部 或者部分记录
3truncate从结构上检查是否存在主外键,如果存在,不让删除
delete 从记录上检查是否存在主外键,如果存在,按参考外键约束进行删除。

事务

事务有一下四个特点:(ACID)

  1. 原子性(Atomic):事务中所有数据的修改,要么全部执行,要么全部不执行。
  2. 一致性(Consistence):事务完成时,要使所有所有的数据都保持一致的状态,换言之:通过事
    务进行的所有数据修改,必须在所有相关的表中得到反映。
  3. 隔离性(Isolation):事务应该在另一个事务对数据的修改前或者修改后进行访问。
  4. 持久性(Durability):保证事务对数据库的修改是持久有效的,即使发生系统故障,也不应该丢
    失。
事务的隔离级别

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CJy6rmbM-1627690913931)(C:\Users\tk\AppData\Roaming\Typora\typora-user-images\1627654491192.png)]

Oracle 默认的隔离级别是 read committed。
Oracle 支持上述四种隔离级别中的两种:read committed 和 serializable。除此之外, Oralce 中还定义
Read only 和 Read write 隔离级别。
Read only:事务中不能有任何修改数据库中数据的操作语句,是 Serializable 的一个子集。
Read write:它是默认设置,该选项表示在事务中可以有访问语句、修改语句,但不经常使用。

丢失更新:两个事务同时存储, 一个存储 100 , 一个存储 200,最终可能至存储了 200 或者 100,那
另一个的更新就没成功,即结果不为预想的 300
脏读:事务 T1 更新了一行数据,还没有提交所做的修改,T2 读取更新后的数据,T1回滚,T2 读取的数
据无效,这种数据称为脏读数据。
不可重复读:事务 T1 读取一行数据,T2 修改了 T1 刚刚读取的记录,T1 再次查询,发现与第一次读取
的记录不相同,称为不可重复读。
幻读:事务 T1 读取一条带 WHERE 条件的语句,返回结果集,T2 插入一条新纪录,恰好也是 T1 的
WHERE 条件,T1 再次查询,结果集中又看到 T2 的记录,新纪录就叫做幻读。

事务的开启

自动开启于 DML 之 insert delete update

事务的结束
  1. 成功
    正常执行完成的 DDL 语句:create、alter、drop
    正常执行完 DCL 语句 GRANT、REVOKE
    正常退出的 SQLPlus 或者 SQL Developer 等客户端
    如果人工要使用隐式事务,SET AUTOCOMMIT ON (只针对一个连接)
    手动提交 :使用 commit
  2. 失败
    rollback ,手动回滚
    非法退出 意外的断电

rollback 只能对未提交的数据撤销,已经 Commit 的数据是无法撤销的,因为 commit 之后已经持久化到数据库中。

JDBC

接口名称作用
java.sql.Connection连接
java.sql.Statement静态处理块
java.sql.PreparedStatement预处理块
java.sql.ResultSet结果集
java.sql.ResultSetMetaData结果集元信息
jdbc步骤
  1. 加载驱动(选择数据库)
  2. 建立连接
  3. 准备sql
  4. 封闭处理块,发送sql
  5. 得到结果集
  6. 处理结果
  7. 关闭资源

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-01JIQsM6-1627690913933)(C:\Users\tk\AppData\Roaming\Typora\typora-user-images\1627655046111.png)]

import java.sql.*;

public class Class001_jdbc01 {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        //加载驱动
        Class.forName("oracle.jdbc.driver.OracleDriver");
        //建立连接
        Connection con = DriverManager.getConnection(
                "jdbc:oracle:thin:@localhost:1521:XE",
                "SCOTT",
                "TIGER"
        );
        //准备sql
        String sql="select * from dept";
        //封装处理块
        Statement state=con.createStatement();
        //发送SQL,得到结果集
        ResultSet resultSet=state.executeQuery(sql);
        //处理结果集
        while (resultSet.next()){
            int deptno=resultSet.getInt(1);
            String dname=resultSet.getString(2);
            String loc=resultSet.getString(3);
            System.out.println(deptno+"-->"+dname+"-->"+loc);
        }
        //关闭资源
        resultSet.close();
        state.close();
        con.close();

    }
}

建立连接

驱动: oracle.jdbc.driver.OracleDriver
url: jdbc:oracle:thin:@db 服务器地址:端口:实例
连接 url->jdbc:oracle:thin:@localhost:1521:XE
用户名: SCOTT
密码: TIGER

Connection con =
DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:XE","SCOTT
","TIGER");

处理块

1.静态处理块Statement

​ Statement 是 Java 执行数据库操作的一个重要接口,用于在已经建立数据库连接的基础上,向数据库发送要执行的 SQL 语句。Statement 对象,用于执行不带参数的简单 SQL 语句。
执行静态 SQL 语句并返回它所生成结果的对象。

特点:

​ 处理 不变的静态的 sql 语句
​ 优点: 直接查看sql ,方便处理错误
​ 缺点:性能不高 拼接 sql 麻烦 可能存在 sql 注入

2.预处理块 PreparedStatemen

​ PreparedStatement 接口继承了 Statement,并与之在两方面有所不同:有人主张,在 JDBC 应用中,如果你已经是稍有水平开发者,你就应该始终以 PreparedStatement 代替 Statement.也就是说,在任
何时候都不要使用 Statement。
由于 PreparedStatement 对象已预编译过,所以其执行速度要快于 Statement对象。因此,多次执行的 SQL 语句经常创建为 PreparedStatement 对象,以提高效率。

特点:

​ 处理 不变的静态的 sql 语句 |可变的 sql 语句 带 ? 的 sql
​ 优点:性能高,方便编写sql 不存在sql注入 安全
​ 缺点:不能直接打印sql语句 不方便处理错误

对固定代码进行封装:

/*
    JDBC工具类
        1.加载驱动
        2.获取连接
        3.关闭资源
 */
public class DBUtil {
    private static Properties pro=new Properties();
    static {
        //1.加载驱动
        //构建 properties对象
        try {
            pro.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        //选择数据库
        try {
            Class.forName(pro.getProperty("server"));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }


    //2.获取连接
    public static Connection getConnection() throws SQLException {
        Connection con=null;
        con= DriverManager.getConnection(
                pro.getProperty("url"),
                pro.getProperty("user"),
                pro.getProperty("password")
        );
        return con;
    }


    //3.关闭资源
    public static void close(ResultSet result, Statement state,Connection conn){
        if(result!= null){
            try {
                result.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if(state!=null){
            try {
                state.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }

    public static void close(Statement state,Connection conn){
        close(null,state,conn);
    }

}

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public  class BaseBao<T> {
    public  List<T>  testQuery(String sql,Class<T> cls,Object ...args){
        //1.获取连接
        Connection con=null;
        PreparedStatement psstate=null;
        ResultSet result=null;
        ResultSetMetaData data=null;
        List<T> list=new ArrayList<>();//存储查询到对象信息
        try {
            con=DBUtil.getConnection();
            //构建预处理块
            psstate=con.prepareStatement(sql);
            //为?赋值
            if(args!=null && args.length!=0){
                for(int i=0;i< args.length;i++){
                    psstate.setObject(i+1,args[i]);
                }
            }
            //执行sql,得到相应行数
            result=psstate.executeQuery();
            //结果集源对象信息
            data = result.getMetaData();
            //从结果集原信息对象上获取当前结果集中每条数据的字段个数
            int columnCount=data.getColumnCount();
            //处理数据
            //循环遍历结果集
            while (result.next()){
                //查询出一条数据,对应创建java中的一个对象
                T obj=cls.newInstance();
                //循环获取每一个列的值,获取每一个属性,为对象属性赋值
                for(int i=1;i<=columnCount;i++){
                    //获取每一条数据的每一个字段的值
                    Object value=result.getObject(i);
                    //判断value是否指向一个java.math.BigDecimal类型的对象,转为对应的int
                    if(value instanceof BigDecimal){
                        BigDecimal big= (BigDecimal)value;
                        value=big.intValue();
                    }
                    //获取字段的名字
                    String columnName= data.getColumnName(i);
                    //获取与字段所对应的属性
                    Field field=cls.getDeclaredField(columnName);
                    //为当前创建的对象的这个属性赋值
                    //忽略权限
                    field.setAccessible(true);
                    field.set(obj,value);
                }
                //把对象放入集合
                list.add(obj);
            }


        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }

        return list;
    }


    /**
     * 增删改
     * @param sql 要执行的sql语句
     * @param args 为?赋值的实参
     * @return 成功与否
     */

    public boolean base(String sql,Object[] args){
        Connection con=null;
        PreparedStatement psstate=null;
        try {
            con=DBUtil.getConnection();
            psstate=con.prepareStatement(sql);

            if(args!=null && args.length!=0){
                for (int i=0;i<args.length;i++){
                    psstate.setObject(i+1,args[i]);
                }
            }
            int rows=psstate.executeUpdate();
            if(rows>0){
                return true;
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }finally {
            DBUtil.close(null,psstate,con);
        }
        return false;
    }

}

/*
    JDBC工具类
        1.加载驱动
        2.获取连接
        3.关闭资源
 */
public class DBUtil {
    private static Properties pro=new Properties();
    static {
        //1.加载驱动
        //构建 properties对象
        try {
            pro.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        //选择数据库
        try {
            Class.forName(pro.getProperty("server"));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }


    //2.获取连接
    public static Connection getConnection() throws SQLException {
        Connection con=null;
        con= DriverManager.getConnection(
                pro.getProperty("url"),
                pro.getProperty("user"),
                pro.getProperty("password")
        );
        return con;
    }


    //3.关闭资源
    public static void close(ResultSet result, Statement state,Connection conn){
        if(result!= null){
            try {
                result.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if(state!=null){
            try {
                state.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
        if(conn!=null){
            try {
                conn.close();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }

    public static void close(Statement state,Connection conn){
        close(null,state,conn);
    }

}

对表进行操作:

import com.yjx.util.DBUtil;
import java.sql.*;


/*
    对用户进行操作
        1.注册用户
        2.登录用户
        3.修改用户信息
        4.注销用户

    预处理块的优点 :
        1.防止sql注入
        2.预先编译,可以提高效率
        推荐使用预处理块代替静态处理块

    注意:
        在java中操作数据库中修改数据的时候,会自动提交事务
 */
public class Class003_User {
    public static void main(String[] args){
        System.out.println(update("zhangsan","321321"));;

    }

    //修改根据用户名修改用户密码
    public static boolean update(String username,String password){
        //1.获取连接
        Connection conn = null;;
        PreparedStatement ps = null;
        boolean flag = false;

        try {
            conn = DBUtil.getConnection();

            //设置手动提交
            conn.setAutoCommit(false);

            //2.构建预处理块
            ps = conn.prepareStatement("update t_user set password=? where username=?");
            //3.为?赋值
            ps.setObject(1,password);
            ps.setObject(2,username);

            //4.执行,得到影响行数
            int rows = ps.executeUpdate();

            //5.判断
            if(rows>0){
                flag = true;
                conn.commit(); //提交
            }else{
                conn.rollback(); //回滚
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            DBUtil.close(ps,conn);
        }


        return flag;
    }


    //登录  : 1)根据用户名与密码一起到数据库中查询,查询到了数据登录成功,否则登录失败   2)根据用于名去查询,得到结果的密码值与用户输入的密码比较,相等登录,不等登录失败
    public static boolean login(String username,String password){
        //1.获取连接
        Connection conn = null;
        PreparedStatement state = null;
        ResultSet result = null;
        try {
            conn = DBUtil.getConnection();
            //2.准备sql
            String sql = "select * from t_user where username=? and password=?";

            //3.构建预处理快
            state = conn.prepareStatement(sql);
            //4.需要为sql中的?占位符传递参数
            state.setObject(1,username);
            state.setObject(2,password);

            //5.执行sql,得到结果集
            result = state.executeQuery();  //预处理块新增的方法 executeQuery()  executeUpdate()
            //5.处理结果
            if(result.next()){
                return true;
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            DBUtil.close(result,state,conn);
        }
        return false;
    }
    //修改
    //注销
    //注册用户
    public static boolean reg(String username,String password){
        //1.获取连接
        Connection conn = null;
        Statement state = null;
        try {
            conn = DBUtil.getConnection();
            //2.准备sql
            String sql = "insert into t_user values('"+username+"',"+password+")";

            //3.构建处理快
            state = conn.createStatement();
            //4.执行sql,得到结果
            int rows  = state.executeUpdate(sql);
            if(rows<=0){
                return false;
            }
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        } finally {
            DBUtil.close(state,conn);
        }

        return true;
    }
}


释放资源

释放资源的原则是 先打开的后关闭, 则我们的顺序一般为: 结果集->处理块->连接

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值