Java研学-jdbc(二)

2023-12-13 17:46:13

六 代码重构

??对于需要反复编写的这种代码,可以将其抽取到工具类中,简化开发,以及将可能会修改的值抽取到properties文件中,解决硬编码的问题
工具类

public class JDBCUtil {
   private static Connection connection=null;
    /*加载驱动创建连接只需要执行一次*/
    static {
        try {
            //创建Properties对象
            Properties properties=new Properties();
            //加载外面的配置文件 通过当前线程获取类加载器,从而获取当前项目根路径下的文件
            InputStream is = Thread.currentThread().getContextClassLoader()
                    .getResourceAsStream("db.properties");
            properties.load(is);
            //读取外部配置文件的内容
            String driver = properties.getProperty("jdbc.driver");
            String url = properties.getProperty("jdbc.url");
            String user = properties.getProperty("jdbc.user");
            String password = properties.getProperty("jdbc.password");
            Class.forName(driver);
            connection= DriverManager.getConnection(url,user,password);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    /*加载驱动创建连接对象*/
    public static Connection getConnection(){
        return connection;
    }
    
    /*关闭对象释放资源*/
    public static void close(Connection connection,Statement statement,ResultSet resultSet){
        try {
            if (resultSet!=null){
                resultSet.close();
            }
            if (statement!=null){
                statement.close();
            }
            if(connection!=null){
                connection.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

properties文件

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql:///web_crud
jdbc.user=root
jdbc.password=root

实体类

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Employee {
    private Long id;
    private String ename;
    private String job;
    private String eid;
    private Integer salary;
}

接口

public interface IEmployeeDao {
    //修改员工
    public void updateEmployee(Employee employee);
    //增加员工
    public void addEmployee(Employee employee);
    //根据id查询员工
    public Employee queryById(int id);
    //查询所有
    public List<Employee> queryALl();
}

实现类

public class EmployeeDaoImpl implements IEmployeeDao {
    /*修改员工*/
    @Override
    public void updateEmployee(Employee employee) {
        try {
            // 使用工具类创建连接对象
            Connection connection = JDBCUtil.getConnection();
            String sql="update t_employee  set eid=? ,ename=? ,job=?,salary=? WHERE id=?";
            PreparedStatement statement = connection.prepareStatement(sql);
            statement.setObject(1,employee.getEid());
            statement.setObject(2,employee.getEname());
            statement.setObject(3,employee.getJob());
            statement.setObject(4,employee.getSalary());
            statement.setObject(5,employee.getId());
            statement.executeUpdate();
            JDBCUtil.close(connection,statement,null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /*增加员工*/
    @Override
    public void addEmployee(Employee employee) {
        try {
            Connection connection = JDBCUtil.getConnection();
            String sql="insert into t_employee(eid,ename,job,salary)values(?,?,?,?)";
            PreparedStatement statement = connection.prepareStatement(sql);
            statement.setObject(1,employee.getEid());
            statement.setObject(2,employee.getEname());
            statement.setObject(3,employee.getJob());
            statement.setObject(4,employee.getSalary());
            statement.executeUpdate();
            JDBCUtil.close(connection,statement,null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /*根据id查询*/
    @Override
    public Employee queryById(int id) {
        try {
            Connection connection = JDBCUtil.getConnection();
            String sql="SELECT * from t_employee WHERE id=?";
            PreparedStatement statement = connection.prepareStatement(sql);
            statement.setObject(1,id);
            //执行查询:将查询的员工信息封装在返回结果集对象中
            ResultSet resultSet = statement.executeQuery();
            //遍历集合
            Employee employee=null;
            while (resultSet.next()){//当遍历的集合中有数据,就获取里面的信息
                //循环依次获取数据库表的一行数据
                //获取字段信息
                Long tid = resultSet.getLong("id");
                String eid = resultSet.getString("eid");
                String ename = resultSet.getString("ename");
                String job = resultSet.getString("job");
                int salary = resultSet.getInt("salary");
                //创建员工对象:使用有参构造实例化对象
                employee=new Employee(tid,eid,ename,job,salary);
            }
            JDBCUtil.close(connection,statement,resultSet);
            //返回员工对象
            return  employee;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    //查询所有
    @Override
    public List<Employee> queryALl() {
        try {
            Connection connection = JDBCUtil.getConnection();
            String sql="SELECT * FROM t_employee";
            PreparedStatement statement = connection.prepareStatement(sql);
            ResultSet resultSet = statement.executeQuery();
            //创建返回的集合对象
            List<Employee> list=new ArrayList<>();
            //遍历结果对象
            while (resultSet.next()){
                //获取每个员工表数据的列字段信息
                Long tid = resultSet.getLong("id");
                String eid = resultSet.getString("eid");
                String ename = resultSet.getString("ename");
                String job = resultSet.getString("job");
                int salary = resultSet.getInt("salary");
                //将获取的数据封装到员工对象
                Employee employee=new Employee(tid,eid,ename,job,salary);
                //将员工对象添加到集合中
                list.add(employee);
            }
            JDBCUtil.close(connection,statement,resultSet);
            return list;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

数据库表

CREATE TABLE `t_employee` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `eid` varchar(10) NOT NULL,
  `ename` varchar(6) NOT NULL,
  `job` varchar(10) DEFAULT NULL,
  `salary` int(10) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `eid` (`eid`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8;

七 事务

1 概述

??事务是指将一组操作括为一个单元,为确保数据库中数据的一致性,数据操作是成组的单元,当单元中的一部分操作失败,整个事务应全部视为错误,所有从起始点以后的操作应全部回退到开始状态。

2 事务的 ACID 属性 – 作用

??① 原子性(Atomicity): 原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
??②一致性(Consistency): 保证数据的完整性,数据不被破坏,事务必须使数据库从一个一致性状态变换到另外一个一致性状态。
??③ 隔离性(Isolation): 指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
??④ 持久性(Durability): 指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响

3 操作步骤

??① 先定义开始一个事务,然后对数据作修改操作,
??② 执行过程中,如果没有问题就提交(commit)事务,此时的修改将永久地保存下来
??③ 如果执行过程中有问题(异常),回滚事务(rollback),数据库将放弃本次事务的所有修改回到开始事务时的状态。

4 例子 – 转账操作

不使用事务 – 异常会导致账户金额问题

public class AccountTest {
    public static void main(String[] args) throws Exception {
        //1.创建连接对象
        Connection connection = JDBCUtil.getConnection();
        //2.创建sql执行对象
        String sql="SELECT * from account WHERE name='大黄'";
        PreparedStatement statement = connection.prepareStatement(sql);
        //3.执行查询转出账号的余额查询
        ResultSet resultSet = statement.executeQuery();
        if (!resultSet.next()){
            System.out.println("账号不存在!");
            return;
        }
        //判断余额是否大于500
        BigDecimal balance = resultSet.getBigDecimal("balance");
        if (balance.intValue()<5000){
            System.out.println("目标账号余额不足!");
            return;
        }
        //4.执行转出操作
        String sql1="update account set balance =balance- 5000 WHERE name='大黄'";
         statement = connection.prepareStatement(sql1);
         statement.executeUpdate();
        //模拟异常
        int num= 1/0;
        //5.执行转入操作
        String sql2="update account set balance =balance+ 5000 WHERE name='大白'";
        statement = connection.prepareStatement(sql2);
        statement.executeUpdate();
        //6.关闭对象
        JDBCUtil.close(connection,statement,resultSet);
    }
}

使用事务

public class AccountTXTest {
    public static void main(String[] args)  {
        Connection connection=null;
        try {
            //1.创建连接对象
            connection = JDBCUtil.getConnection();
            //开启事务手动提交
            connection.setAutoCommit(false);
            //2.创建sql执行对象
            String sql="SELECT * from account WHERE name='大黄'";
            PreparedStatement statement = connection.prepareStatement(sql);
            //3.执行查询转出账号的余额查询
            ResultSet resultSet = statement.executeQuery();
            if (!resultSet.next()){
                System.out.println("账号不存在!");
                return;
            }
            //判断余额是否大于500
            BigDecimal balance = resultSet.getBigDecimal("balance");
            if (balance.intValue()<5000){
                System.out.println("目标账号余额不足!");
                return;
            }
            //4.执行转出操作
            String sql1="update account set balance =balance- 5000 WHERE name='大黄'";
            statement = connection.prepareStatement(sql1);
            statement.executeUpdate();
            //模拟异常
            //int num= 1/0;
            //5.执行转入操作
            String sql2="update account set balance =balance+ 5000 WHERE name='大白'";
            statement = connection.prepareStatement(sql2);
            statement.executeUpdate();
            //手动提交事务
            connection.commit();
            System.out.println("转账成功,提交事务!");
            //6.关闭对象
            JDBCUtil.close(connection,statement,resultSet);
        } catch (Exception e) {
            System.out.println("转账异常,回滚事务!");
            e.printStackTrace();
            try {
               //转帐出现异常,回滚事务
                connection.rollback();
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
        }
    }
}

工具类

public class JDBCUtil {
   private static Connection connection=null;
    /*加载驱动创建连接只需要执行一次*/
    static {
        try {
            Class.forName("com.mysql.jdbc.Driver");
             connection= DriverManager.getConnection("jdbc:mysql:///web_crud","root","root");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static Connection getConnection(){
        return connection;
    }
    public static void close(Connection connection,Statement statement,ResultSet resultSet){
        try {
            if(connection!=null){
                connection.close();
            }
            if (statement!=null){
                statement.close();
            }
            if (resultSet!=null){
                resultSet.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

数据库表

CREATE TABLE account(
id BIGINT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(20),
balance DECIMAL(10,2)
);
INSERT INTO account(name,balance) VALUES('大黄',18000),('大白',0);

5 小结

① 默认事务在执行完 DML 操作就自动提交.
② 查询操作,不需要事务
③ 代码正确无异常,但数据库数据不变,有可能是没有提交事务
④ MySQL ,中 InnoDB 存储引擎支持事务,支持外键,MyISAM 不支持事务.

文章来源:https://blog.csdn.net/zhlyxx/article/details/134974618
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。