zoukankan      html  css  js  c++  java
  • Commons dbutils、pool、dbcp以及JDBC事务

    1.dbutils包:

    提供执行sql语句的功能,简化过程

    (1)执行添加、删除语句

        public static void add() throws SQLException {
            QueryRunner qr = new QueryRunner();//实例化
            Connection conn = DButil.getConn();//获取数据库连接
            String sql = "insert into userscount(uname,upwd) values(?,?)";
            Object[] obj = {"god","123456"};
            int pow = qr.update(conn, sql,obj);//传入链接对象,sql语句,obj对象,obj数组内的两个值对应两个预留字符
            conn.close();
            if(pow>0) {
                System.out.println("添加成功!");
            }else {
                System.out.println("添加失败!");
            }
        }
    public static void delete() throws SQLException {
            QueryRunner qr = new QueryRunner();
            Connection conn = DButil.getConn();
            String sql = "delete from userscount where uid=?";
            int pow = qr.update(conn,sql,1);//可以直接传入多个参数来对应预留字符
            conn.close();
            if(pow>0) {
                System.out.println("删除成功!");
            }else {
                System.out.println("删除失败!");
            }
    }

    增删改都调用update()方法。

    (2)查询

    查询调用query()方法,最常用的是将查询的结果存入javabean对象中,然后把多个结果存入集合中

    public static void findBeanList() throws SQLException {
            QueryRunner qr = new QueryRunner();
            Connection conn = DButil.getConn();
            String sql = "select * from userscount";
            List<UserBean> list = qr.query(conn, sql,new BeanListHandler<UserBean>(UserBean.class));
            //查询到的每条记录存入对象中,对象存入list中
            for(UserBean b:list) {
                System.out.println(b.getUid()+"::"+b.getUname()+"::"+b.getUpwd());
            }
            conn.close();
    }

    其他的查询方法:

    public static void find() throws SQLException {
            QueryRunner qr = new QueryRunner();
            Connection conn = DButil.getConn();
            String sql = "select * from userscount";
            Object[] obj = qr.query(conn,sql, new ArrayHandler());//查询到的第一条记录存入集合
            for(Object o:obj) {
                System.out.println(o);
            }
            conn.close();
    }
    public static void findList() throws SQLException {
            QueryRunner qr = new QueryRunner();
            Connection conn = DButil.getConn();
            String sql = "select * from userscount";
            List<Object[]> list = qr.query(conn,sql, new ArrayListHandler());//查询到的每条记录记录存入Object数组然后放入Arraylist中
            for(Object[] o:list) {
                for(Object obj:o) {
                    System.out.println(obj);
                }
            }
            conn.close();
    }
    public static void findBean() throws SQLException {
            QueryRunner qr = new QueryRunner();
            Connection conn = DButil.getConn();
            String sql = "select * from userscount";
            UserBean ub = qr.query(conn, sql,new BeanHandler<UserBean>(UserBean.class));//查询到的第一条记录存入对象中
            conn.close();
    }
    public static void findScalar() throws SQLException {
            QueryRunner qr = new QueryRunner();
            Connection conn = DButil.getConn();
            String sql = "select count(*) from userscount group by uname";
            long count = qr.query(conn, sql,new ScalarHandler<Long>());//查找指定数据
            System.out.println(count);
            conn.close();
    }

    2.连接池(pool、dbcp)

    提供DataSource接口(java中提供的连接池)的实现类BasicDataSource,连接数据库并返回一个连接池对象

    public class ConnPool {
        public static DataSource getDataSource() {
            try(InputStream in = ConnPool.class.getClassLoader().getResourceAsStream("DButil.properties");){
                Properties pro = new Properties();
                pro.load(in);
                String driver = pro.getProperty("driver");
                String url = pro.getProperty("url");
                String user = pro.getProperty("user");
                String password = pro.getProperty("password");
                BasicDataSource dataSource = new BasicDataSource();
                dataSource.setDriverClassName(driver);
                dataSource.setUrl(url);
                dataSource.setUsername(user);
                dataSource.setPassword(password);
                return dataSource;
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException("连接数据库失败!"+e);
            }
        }
    }

    如何使用连接池:

    将连接池对象传入QueryRunner的构造方法中

    public static void findMap() throws SQLException {
            QueryRunner qr = new QueryRunner(ConnPool.getDataSource());//将连接池对象传入
            String sql = "select * from userscount";
            Map<String, Object> map = qr.query(sql,new MapHandler());//key是字段名,value是数据
            Set<Entry<String,Object>> entry = map.entrySet();
            for(Entry<String,Object> e:entry) {
                System.out.println(e.getKey()+":"+e.getValue());
            }
    }

     3.JDBC事务

    一般情况下,sql语句在excute后会自动将数据提交到数据库,而使用手动事务后,数据会暂存在事务日志中,可以防止多条语句执行时,其中一条语句执行失败而其他语句成功执行的情况,同时可以回滚数据取消操作。

    public class Demo {
    
        public static void main(String[] args){
            try {
                Connection conn = DButil.getConn();
                String sql1 = "insert into userscount(uname,upwd) values(?,?)";
                String sql2 = "insert into userscoun(uname,upwd) values(?,?)";//故意写错,表名少个t
                //关闭自动提交事务
                conn.setAutoCommit(false);
                PreparedStatement ps1 = conn.prepareStatement(sql1); 
                ps1.setString(1, "admin");
                ps1.setString(2, "123456");
                ps1.executeUpdate();
                PreparedStatement ps2 = conn.prepareStatement(sql2); 
                ps2.setString(1, "user1");
                ps2.setString(2, "123456");
                ps2.executeUpdate();
                // 手动提交事务
                conn.commit();
                //conn.rollback();回滚数据
                //上面两条数据都没有被加入数据库
                DButil.close(ps1, conn);
            } catch (Exception e) {
                System.out.println("添加数据失败!");
            }
        }
    }

     需要注意的是,手动事务能成功的前提是执行sql语句的statement来自于同一个Connection,一般DAO层的方法是在Service层执行的,所以在Service层的方法中,每个方法内的DAO层方法要使用同一个Connection,将其作为参数传入DAO层的方法:

    public void method(){
        Connection conn =DButil.getConn();
        conn.setAutoCommit(false);
        方法(conn,其他参数) ;
        方法(conn,其他参数);
        .
        .
        .
        .
        conn.commit();
    
    }

     利用ThreadLocal改进上述方法:

    DButil内改动

    private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();
    
      //获取连接
        public static Connection getCurrentConn() throws SQLException {
            Connection conn = tl.get();
            if(conn==null) {
                tl.set(getConn());
            }
            return conn;
        }
        //开启手动事务
        public static void startManul() throws SQLException {
            Connection conn = getCurrentConn();
            conn.setAutoCommit(false);
        }
        //回滚
        public static void manulRollback() throws SQLException {
            Connection conn = getCurrentConn();
            conn.rollback();
        }
        //手动提交
        public static void manulCommit() throws SQLException {
            Connection conn = getCurrentConn();
            conn.commit();
        }

    DAO层方法:

    public void method(){
        Connection conn =DButil.getCurrentConn();
        业务逻辑....
    
    }

    Service层改动:

    public void method(){
        DButil.startManul();
        方法(参数) ;
        方法(参数);
        .
        .
        .
        .
        DButil.manulCommit();
    
    }finally{
        manulRollback();
    }
  • 相关阅读:
    C# FTP功能实现(转载)
    Invoke和BeginInvoke的使用(转载)
    .NET中各种数据库连接大全(转载)
    最近关注的网络资料(书签)
    SQL语句总结(转载)
    线程池和定时器——多线程的自动管理(转载)
    C#程序安装部署(转载)
    TcpClient.Connect函数连接超时的问题(转载)
    C# 各种定时器比较(转载)
    SQL SERVER中对日期字段(datetime)比较(转载)
  • 原文地址:https://www.cnblogs.com/whwjava/p/9035534.html
Copyright © 2011-2022 走看看