数据库的元数据及事务

元数据、事务及手动添加事务、利用缓存进行批处理数据、利用Connection的重载的prepareStatemen()方法获取表的某些字段的值。


package test;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.List;
import org.junit.Test;
import dao.EmpDao;
import entity.Emp;
import util.DBUtil;
----------------------------------------------------------------------------------------
元数据(MetaData)
    - 元:根本、本质
    - 元数据:数据的本质,数据的描述/概述
    - 用来描述数据的数据叫元数据

结果集元数据(ResultSetMetaData)
    - 用来描述结果集的数据
    - 如:返回的结果有几列、列名是什么、列的类型是什么

public class Test {
    
    /**
     * ResultSetMetData(了解)
     */
    @Test
    public void test(){
        Connection con = null;
        try {
            con = DBUtil.getConnection();
            String sql = "SELECT * FROM emp ";
            PreparedStatement ps = con.prepareStatement(sql);
            ResultSet rs = ps.executeQuery();
            /*
             * 获取结果集元数据。
             * 元数据中存储了描述该结果集的信息。
             */
            ResultSetMetaData md = rs.getMetaData();
            System.out.println(md.getColumnCount());//字段数
            System.out.println(md.getColumnName(1));//第一列的字段名
            System.out.println(md.getColumnClassName(1));//第一列的字段类型
            
        } catch (SQLException e) {
            
            e.printStackTrace();
            throw new RuntimeException("查询员工失败!",e);
        }finally{
            DBUtil.close(con);
        }
    }
}
-----------------------------------------------------------------------------------------
事务:

什么叫事务?
满足如下特征的数据库访问叫事务:1. 原子性:事务是完整的,要么都成功,要么都失败。
                2. 一致性:事务前后的数据要保持一致,即收支平衡。
                3. 隔离性:事务过程中的数据不能被别人访问,需要受隔离/保护。

                 4. 持久性:事务一旦达成,就永久有效。

JDBC自动管理事务,当调用executeUpdate()时,JDBC会自动提交事务。

如何手动管理事务?
    con.setAutoCommit(false);//改为手动提交事务
    con.commit(); //提交
    con.rollback(); //回滚



public class Test {    
    /**
     * 模拟转账
     * 1.验证收款方账户是否存在。
     * 2.验证付款方账户余额是否充足。
     * 3.付款方账户减N元
     * 4.收款方账户加N元。
     */
    @Test
    public void test1(){
        //假设用户在atm上输入了如下信息:
        int padId = 1;//付款方账户
        int recId = 2;//收款方账号
        double mny = 1000.0;//转账金额
        
        Connection con = null;
        try {
            con = DBUtil.getConnection();
            
            //1.验证收款方账户是否存在。            
            String sql = "SELECT * FROM accounts "
                       + "WHERE id=?";
            PreparedStatement ps = con.prepareStatement(sql);
            ps.setInt(1, recId);
            ResultSet rs = ps.executeQuery();
            if(!rs.next()){
                System.out.println("收款账号不存在!");
                throw new SQLException("收款账号不存在!");
            }
            double recMoney = rs.getDouble("money");//记录收款方余额,便于之后转

账计算余额
            
            //2.验证付款方账户余额是否充足。
            sql = "SELECT * FROM accounts "
                + "WHERE id=? ";
            ps = con.prepareStatement(sql);
            ps.setInt(1, padId);
            rs = ps.executeQuery();
            rs.next();
            double payMoney = rs.getDouble("money");
            if(payMoney<mny){
                System.out.println("余额不足!");
                throw new SQLException("余额不足!");
            }            
            
            //设置手动管理事务(取消自动提交事务)
            con.setAutoCommit(false);
            
            //3.付款方账户减N元
            sql = "UPDATE accounts "
                    + "SET money=?"
                    + "WHERE id=?";
            ps = con.prepareStatement(sql);
            ps.setDouble(1, payMoney-mny);
            ps.setInt(2, padId);
            ps.executeUpdate();
            
            //假设此处有个错误!
            //Integer.valueOf("abc");
            
            //4.收款方账户加N元。
            sql = "UPDATE accounts "
                    + "SET money=? "
                    + "WHERE id=?";
            ps = con.prepareStatement(sql);
            ps.setDouble(1, recMoney+mny);
            ps.setInt(2, recId);
            ps.executeUpdate();

            //当账户转账流程正常结束时统一提交事物!
            con.commit();
        } catch (Exception e) {
            //当转账过程发生异常时回滚事物!
            try {
                con.rollback();
            } catch (SQLException e1) {
                e1.printStackTrace();
                throw new RuntimeException("回滚失败!");
            }
            e.printStackTrace();
            throw new RuntimeException("转账失败!",e);
        }finally{
            DBUtil.close(con);
        }        
    }
213438_OkA7_2708082.png 
    /**
     * 批量添加员工
     */
    @Test
    public void test2(){
        Connection con = null;
        try {
            con = DBUtil.getConnection();
            con.setAutoCommit(false);//取消自动提交事务
            
            //批量发送数据的前提是他们的SQL一样
            String sql = "INSERT INTO emp "
                    + "VALUES (seq_emp.nextval,?,?,?,?,?,?,?)";
            PreparedStatement ps = con.prepareStatement(sql);
            for(int i=1;i<=108;i++){
                ps.setString(1, "好汉"+i);
                ps.setString(2, "打劫");
                ps.setInt(3, 0);
                ps.setDate(4, null);
                ps.setDouble(5, 1000.0);
                ps.setDouble(6, 8000);
                ps.setInt(7, 3);
                
                //将本条数据暂存到ps内
                ps.addBatch();
                
                //每个n次批量发送一次数据
                if(i%30==0){
                    ps.executeBatch();
                    
                    //清除缓存的数据,便于下次发送
                    ps.clearBatch();
                }
            }
            //余下的数据单独发送一次
            ps.executeBatch();
            
            con.commit();
        } catch (SQLException e) {
            try {
                con.rollback();
            } catch (SQLException e1) {
                e1.printStackTrace();
                throw new RuntimeException("回滚失败!");
            }
            e.printStackTrace();
            throw new RuntimeException("批量添加员工失败!",e);
        }finally{
            DBUtil.close(con);
        }
    }
    
    /**
     * 添加部门,然后向此部门内添加员工
     */
    @Test
    public void test3(){
        //假设要添加的部门信息如下
        String dname = "财务";
        String loc = "北京";
        
        //假设要添加的员工数据如下
        String ename = "张三";
        String job = "经理";
        double sal = 6000;
        double comm = 546;
        
        String ename2 = "李四";
        String job2= "职员";
        double sal2 = 4000;
        double comm2 = 1546;
        
        Connection con = null;        
        try {
            con = DBUtil.getConnection();
            con.setAutoCommit(false);
            
            //先添加部门
            String sql = "INSERT INTO depts "
                    + "VALUES (seq_depts.nextval,?,?)";
            //参数2是一个数组,存的是希望被ps记住的字段的名称。
            PreparedStatement ps = con.prepareStatement(sql,new String[]
{"deptno","loc"});
            ps.setString(1, dname);
            ps.setString(2, loc);
            ps.executeUpdate();
            /*
             * 从ps中获取它之前记录的字段的值
             * 返回的结果集中只有一条数据,存的就是记录的那些字段的值
             * rs.getXXX(参数);中的参数代表你在数组中所填的第几个参数。
             */
            ResultSet rs = ps.getGeneratedKeys();
            rs.next();
            int deptno = rs.getInt(1);
            String dname3 = rs.getString(2);
            System.out.println(deptno);
            System.out.println(dname3);
            
            //添加员工1
            sql = "INSERT INTO emp "
                    + "VALUES (seq_emp.nextval,?,?,?,?,?,?,?)";
            ps = con.prepareStatement(sql);
            ps.setString(1, ename);
            ps.setString(2, job);
            ps.setInt(3, 0);
            ps.setDate(4, null);
            ps.setDouble(5,sal);
            ps.setDouble(6,comm);
            ps.setInt(7,deptno);
            ps.executeUpdate();
            //添加员工2
            sql = "INSERT INTO emp "
                    + "VALUES (seq_emp.nextval,?,?,?,?,?,?,?)";
            ps = con.prepareStatement(sql);
            ps.setString(1, ename2);
            ps.setString(2, job2);
            ps.setInt(3, 0);
            ps.setDate(4, null);
            ps.setDouble(5,sal2);
            ps.setDouble(6,comm2);
            ps.setInt(7,deptno);
            ps.executeUpdate();
                    
            con.commit();
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException("添加部门员工信息失败!",e);
        }finally{
            DBUtil.close(con);
        }                
    }

转载于:https://my.oschina.net/langgege/blog/667824

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值