Java学习日志Day30_数据库的事务_Jdbc

一、数据库的事务

事务的概念

  1. 将整个事务看成一个整体,要么同时执行成功,要么同时执行失败

    start transaction ; 开启事务
    如果执行过程中不存在问题,事务提交:commit;
    如果执行过程中有问题:回滚事务:rollback ;(回滚到开启事务时的状态)

举例:
-- 创建一个账户表
CREATE TABLE account(
   id INT PRIMARY KEY AUTO_INCREMENT ,
   NAME VARCHAR(10),
   balance INT 
 
) ;

INSERT INTO account(NAME,balance) VALUES('zhangsan',1000),('lisi',1000) ;



-- 张三要给李四转账500
-- 这个业务操作需要执行两次sql才能完成
-- 张三-500
UPDATE account SET balance = balance - 500 WHERE id = 1 ;


中间出问题了

-- 李四+500

UPDATE account SET balance = balance + 500 WHERE id = 2 ;
  1. 问题:没有使用事务管理起来,造成了我们的整个业务操作只有zhangsan-500了,而lisi没有执行sql
    不安全问题!
开启事务:start tansaction ;
-- select @@autocommit;  -- @@在MySQL是一个全局变量:查看当前的事务提交状态码:默认是1(自动提交)
-- 可以通过 set @@autocommit = 0 ; 取消自动提交
  1. 什么时候时使用Transaction管理?
    当一个业务操作需要频繁的操作SQL(两个或者多个以上的增删改),
    这个时候需要使用事务管理,防止多个SQL执行过程中存在异常,导致和预期值不同!
以上代码优化:
-- 将转账业务的这个sql语句使用事务管理   (insert into,update,delete :都可以使用管理起立)
START TRANSACTION ;

-- 如果转账中出现问题了  必须回滚(默认情况下:回滚到开启事务时的状态)
-- 张三-500
UPDATE account SET balance = balance - 500 WHERE id = 1 ;

-- 此处有问题了

-- 李四+500
UPDATE account SET balance = balance + 500 WHERE id = 2 ;

-- 必须提交事务:如果没有提交事务(下次查询的时候:依然转账之前的状态 )
COMMIT ;


-- rollback ; -- (如果存在问题就要回滚)事务回滚 

SELECT * FROM account ;
  1. 事务的特性:
    原子性:每一个事务是独立的,不可再拆分.事务的执行过程中多个sql要么同时执行成功,要么同时失败
    一致性:事务执行前和执行后:总量保持不变
    隔离性:事务和事务之前是独立(业务和业务之间不相互影响)
    持久性:事务对sql的执行是永久性的(提交事务之后)!
  2. 事务的隔离级别:隔离级别不同,引发线程安问题不同:
    脏读:一个事务读取到另一个没有提交的事物(非常严重的!)
    读未提交 read uncommitted :不能够防止脏读(安全性最差)
    读已提交 read committed :能够有效防止脏读,但是不可重复读防止不了
    (两次读取的内容不一样!)
    可重复读 repeatable read (mysql就是这个级别)
    串行化 serializable
  3. SELECT @@tx_isolation;-- 查看事务的隔离级别
    – set global transaction isolation level 级别名称;设置级别

二、JDBC

Jdbc的引入

  1. jdbc涉及到的API
    1)java.sql.DriverManager 类 :驱动管理类 :管理jdbc的驱动类 com.mysql.jdbc.Driver
    管理一组诸如JDBC的驱动程序(驱动服务) 类似于 计算机上的那些驱动管理器
    涉及的方法:
 		public static Connection getConnection(String url, String user, String password)
     获取数据库连接对象
     参数1:url地址(jdbc协议 + mysql协议)
     jdbc:mysql://localhost:3306/myee_2104
         jdbc: jdbc协议
         mysql://(mysql协议)
        localhost:3306    (域名:端口号)
        连接的具体的数据库名
     参数2:user: 用户名(root)
     参数3:password:密码


        注册驱动
         public static void registerDriver(Driver driver) :形参需要的是java.sql.Driver它的子实现类对象
                                            com.mysql.jdbc.Driver

         通过导入的驱动jar包
         class Driver implements java.sql.Drvier{
              public Driver() throws SQLException {
               }
            只要这个类一加载
             static {
                    try {
                        DriverManager.registerDriver(new Driver()); //注册驱动了
                    } catch (SQLException var1) {
                        throw new RuntimeException("Can't register driver!");
                    }
                }
         }


         2)java.sql.Connection:接口   与数据库的特定连接会话对象

            它可以管理事务,针对事务提供一些功能:
            void setAutoCommit(boolean autoCommit):参数为true,表示自动提交事务(默认的)false,表示关闭自动提交事务

            void rollback():回滚事务,释放连接到对象,并回滚到开启事务时的状态

            void commit()throws SQLException:提交事务


            获取执行对象以及预编译对象
            Statement createStatement() throws SQLException: 获取执行对象

            PreparedStatement prepareStatement(String sql):通过预编译sql语句获取预编译对象
            预编译的sql----参数化sql   (?:占位符号)
            String sql = "update  account  set balance = balance - ? where id = ?;


3)Statement:java.sql包下的接口
        执行静态 SQL 语句并返回它所生成结果的对象。
        int executeUpdate(String sql):执行静态sql语句
                执行DDL,DML 都可以

        ResultSet executeQuery(String sql):执行DQL语句
                "select * from account"

4)java.sql.PreparedStatement:预编译对象

    有一些功能:
        ResultSet executeQuery():不带参:sql已经编译了,执行DQL语句
                select...
        int executeUpdate():执行参数化的sql语句:
                    insert into,,,
                    delete...
                    update....


5)java.sql.ResultSet:
        表示的数据库的结果集数据表

        通过这个接口可以实现 查询结果(多条,还是单条记录),都可以ReulstSet遍历结果
        然后就可以封装实体

        方法:
                boolean next():将光标向前移动一行(前一行存在有效数据) :true,向前一行



        UserUser类
        id 字段                               id属性
        name 字段                             name属性
        address字段                           address属性
  1. JDBC原生的操作步骤:
    1)导入mysql驱动jar包
    2)加载驱动
    3)创建数据库的连接对象
    4)准备好sql语句
    5)通过数据库的连接对象获取执行对象:Statement
    6)更新 或者查询(执行sql语句)
    7)获取结果并释放资源
举例:
public class JdbcDemo {
    public static void main(String[] args) throws Exception {

        //1)导入mysql驱动jar包
        //2)加载驱动  :为了保证向下兼容性:DriverManager :驱动管理类 不用他
        Class.forName("com.mysql.jdbc.Driver") ;
       // DriverManager.registerDriver(new com.mysql.jdbc.Driver());


        //3)创建数据库的连接对象
       // public static Connection getConnection(
          //      String url,:url地址:连接的mysql的哪个数据库
          //  String user,   :用户名
         //       String password) mysql的   密码


        Connection conn = DriverManager.getConnection(
                "jdbc:mysql:///myee_2104",
                "root",
                "123456"
        );
        System.out.println(conn);
        System.out.println("准备执行...");

        //4)准备好sql语句
        String sql = "update  account  set balance = balance - 500 where id = 13" ;
        //5)通过数据库的连接对象获取执行对象:Statement
        //Statement createStatement()throws SQLException
        Statement stmt = conn.createStatement() ;
        System.out.println(stmt);
        //6)执行
        //int executeUpdate(St
        // ring sql)throws SQLException
        int count = stmt.executeUpdate(sql);

            System.out.println("影响了"+count+"行");


        System.out.println("修改成功...");

        //释放资源
        stmt.close();
        conn.close();
    }
}
举例:
/*使用Statement执行DDL语句
 *      创建一个tea表
 *      DML语句*/
public class JdbcDemo2 {

    public static void main(String[] args) {
        Connection conn = null ;
        Statement stmt = null ;

        try {
            //注册驱动
            Class.forName("com.mysql.jdbc.Driver") ;
            //获取数据库的链接对象
             conn = DriverManager.getConnection(
                    "jdbc:mysql://localhost:3306/myee_2104",
                    "root",
                    "123456"
            );

             //获取执行对象
            stmt = conn.createStatement();
            //准备sql
            //DDL
         /*   String sql ="CREATE TABLE tea(" +
                    " id INT PRIMARY KEY AUTO_INCREMENT," +
                    " NAME VARCHAR(10), " +
                    " gender VARCHAR(3)," +
                    " address VARCHAR(10)," +
                    " salary INT" +
                    "); " ;*/

          //DML语句
            String sql = "insert  into  tea (name,gender,address,salary) values('刘备','男','西安市',8000)" ;

            System.out.println(sql);

            //执行sql
            int count = stmt.executeUpdate(sql);
            System.out.println(count);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            if(stmt!=null){
                try {
                    stmt.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }

            if(conn!=null){
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
举例:
/* 工具类:
 *
 * 封装获取连接对象的功能
 * 关闭资源:封装一个close()
 * /
举例:

jdbc.properties:
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/myee_2104
user=root
password=123456

public class JdbcUtils {
    private static String url = null ; //url地址
    private static String user = null ;//用户名
    private static String password = null ;//密码
    private static String driver = null ;//驱动


    //模仿com.mysql.jdbc.Driver  加载driver类的时候提供了静态代码块:
    //注册驱动


    //也可以加载JdbcUtils这个类的时候,提供一个静态代码块

    static{

        try {
            //通过读取配置文件获取url,user,password,driver
            //创建属性集合类对象
            Properties prop = new Properties() ;
            //读取配置文件夹
            InputStream inputStream =
                    JdbcUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
            prop.load(inputStream);
            System.out.println(prop);

            //通过key获取value
            url = prop.getProperty("url");
            user = prop.getProperty("user") ;
            password = prop.getProperty("password") ;
            driver = prop.getProperty("driver") ;

            //加载驱动
            Class.forName(driver) ;
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }



    private JdbcUtils(){} //构造私有化


    //封装一个获取连接对象的功能:静态功能
    public static Connection getConnection(){

        Connection conn = null ;
        try {
            conn = DriverManager.getConnection(url, user, password);
            return conn ;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null ;

    }


    //关闭资源
    //DDL/DML语句的增删改---->返回int,影响的行数  DDL语句,返回0
    public static void close(Statement stmt,Connection conn) {
            close(null,stmt,conn);
    }

    //针对DQL语句:查询---获取结果集:ResultSet
    public static void close(ResultSet rs,Statement stmt,Connection conn){
        if(rs!=null){
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if(stmt!= null){
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        if(conn!= null){
            try {

                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }


    //测试是否能够获取Connection对象
    public static void main(String[] args) {

        Connection connection = JdbcUtils.getConnection();
        System.out.println(connection);
    }
}

/* 加入封装好的工具类:来tea表
 */
 public class Demo3 {
    public static void main(String[] args) {

        Connection conn = null ;
        Statement stmt = null ;
        try{

            //获取连接
            conn = JdbcUtils.getConnection();
            //准备sql
            String sql = "update tea set name = '张飞' where id = 1" ;
            //获取执行对象
             stmt = conn.createStatement();
             //执行sql
            int count = stmt.executeUpdate(sql);
            System.out.println(count);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            JdbcUtils.close(stmt,conn);
        }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

igfff

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值