zoukankan      html  css  js  c++  java
  • JDBC化繁为简

    众所周知,jdbc可谓是java连接数据库最基本的方法,通过DriverManager拿到connection,再从connection拿到statement,再从statement中进一步操作得到结果,这是标准的步骤。但是每次都要在一个dao层的类中都要写一次这些方法才能使用,确实很烦人,也很繁琐,写来写去这些东东,间接增加工作量,也令人烦,如下代码。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    public class Dao {
     
        //此段代码未经测试,可能有错
        public boolean add2(User user) throws Exception {
            /*************重复代码*************/
            String userName = "root";
            String password = "19501517";
            String url = "jdbc:mysql://localhost/test";
            Class.forName("com.mysql.jdbc.Driver");
            /*************重复代码*************/
        
          String sql = "insert into user(id, name, password) value(null, ?, ?)";
            Connection connection = (Connection) DriverManager.getConnection(url,
                    userName, password);
     
            PreparedStatement stat = (PreparedStatement) connection
                    .prepareStatement(sql);
            stat.setString(1, user.getUsername());
            stat.setString(2, user.getPassword());
            stat.execute();
             
            return true;
        }
    }

    数据库中有一个表

     

    有一个基本的模型User

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    package com.model;
     
    public class User {
     
        private int id;
        private String username;
        private String password;
         
        public User(String username, String password) {
            this.username = username;
            this.password = password;
        }
         
        /****************省略get和set方法***************/
    }

    为了减少代码量,引入工厂设计模式(具体请自行了解工厂模式),在工厂中把必要的步骤完成,到需要connection的时候,从工厂中拿出来,这样就可以省去很多不必要的繁琐步骤。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    /**
     * 工厂类,用于生产和关闭数据库连接。
     * @author LiuYeFeng
     * @date 2014-7-30 上午11:40:27
     * @CopyRight 2014 TopView Inc
     * @version V1.0
     *
     */
    public class DBUtil {
         
        private static final String USER_NAME = "root";
        private static final String PASSWORD = "19501517";
        private static final String URL = "jdbc:mysql://localhost/test";
         
        private static Connection connection = null;
     
        static {
            try {
                Class.forName("com.mysql.jdbc.Driver");
            catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
         
        /**
         * 用于得到一个connection
         * @return 返回一个可用于操作的connection
         */
        public static Connection getConnection() {
             
            //需要一个connection,我就生产一个。
            if( connection == null){
                try {
                    connection = (Connection) DriverManager.getConnection(URL, USER_NAME, PASSWORD);
                catch (SQLException e) {
                    e.printStackTrace();
                }
            }
             
            return connection;
        }
         
        /**
         * 关闭connection
         * @return 正常关闭则返回true
         */
        public static boolean closeConnection() {
             
            if(connection != null) {
                try {
                    connection.close();
                catch (SQLException e) {
                    e.printStackTrace();
                }
            }
             
            return true;
        }
    }

     那么dao层就可以这样子写

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    /**
     * 用于持久化user的dao层
     * @author LiuYeFeng
     * @date 2014-7-30 上午11:45:57
     * @CopyRight 2014 TopView Inc
     * @version V1.0
     *
     */
    public class Dao {
     
        /**
         * 往数据库中增加一个user
         * @param user 需要持久化到数据库中的user
         * @return 添加成功返回true,否则返回false
         * @throws SQLException 把可能产生的异常抛出来,让service捕捉处理
         */
        public boolean add(User user) throws SQLException {
            Connection connection = DBUtil.getConnection();
            String sql = "insert into user(id, name, password) value(null, ?, ?)";
     
            PreparedStatement stat = (PreparedStatement) connection
                    .prepareStatement(sql);
            stat.setString(1, user.getUsername());
            stat.setString(2, user.getPassword());
            stat.execute();
     
            DBUtil.closeConnection();
     
            return true;
        }
         
    }

     对应的业务逻辑层

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    /**
     * user的事务类
     * @author LiuYeFeng
     * @date 2014-7-30 上午11:50:40
     * @CopyRight 2014 TopView Inc
     * @version V1.0
     *
     */
    public class Service {
         
        Dao dao = new Dao();
     
        /**
         * 处理添加一个用户的业务逻辑
         * @param username 需要持久化的user的名字
         * @param password 需要持久化的User的密码
         */
        public void addUser(String username, String password) {
            User user = new User(username, password);
            boolean flag = false;
             
            try {
                flag = dao.add(user);
            catch (SQLException e) {
                e.printStackTrace();
            }
             
            System.out.println("add user result:" + flag);
        }
    }

    测试类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class MainTest {
     
        public static void main(String[] args) {
            String username = "张三";
            String password = "password";
            Service service = new Service();
             
            service.addUser(username, password);
        }
    }

    这样看起来好像是可以了的样子,代码量减少了,也没有那么繁琐的步骤了。但是,这种代码还是存在问题,万一 一个业务需要调用两次dao,而且调用过程中一个dao如果出了问题所有操作都要回滚,简而言之叫事务管理,如果用以上方法的话无法达到事务管理的效果,那就要对代码进行进一步优化,在new一个dao的同时,把一个connection从service传进来,然后在service进行事务处理就可以了。

    优化后的dao

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    /**
     * 用于持久化user的dao层
     * @author LiuYeFeng
     * @date 2014-7-30 上午11:45:57
     * @CopyRight 2014 TopView Inc
     * @version V2.0
     *
     */
    public class Dao {
         
        /**
         * 在new一个dao的同时,把一个connection传进来
         */
        Connection connection = null;
         
        public Dao(Connection connection) {
            this.connection = connection;
        }
     
        /**
         * 往数据库中增加一个user
         * @param user 需要持久化到数据库中的user
         * @return 添加成功返回true,否则返回false
         * @throws SQLException 把可能产生的异常抛出来,让service捕捉处理
         */
        public boolean add(User user) throws SQLException {
            String sql = "insert into user(id, name, password) value(null, ?, ?)";
     
            PreparedStatement stat = (PreparedStatement) connection
                    .prepareStatement(sql);
            stat.setString(1, user.getUsername());
            stat.setString(2, user.getPassword());
            stat.execute();
     
            return true;
        }
    }

     优化后的service层

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    /**
     * user的事务类
     * @author LiuYeFeng
     * @date 2014-7-30 上午11:50:40
     * @CopyRight 2014 TopView Inc
     * @version V2.0
     *
     */
    public class Service {
         
        Connection connection = DBUtil.getConnection();
        Dao dao = new Dao(connection);          //new一个dao的同时,传一个connection进去
     
        /**
         * 处理添加一个用户的业务逻辑
         * @param username 需要持久化的user的名字
         * @param password 需要持久化的User的密码
         */
        public void addUser(String username, String password) {
            User user = new User(username, password);
            boolean flag = false;
             
            try {
                connection.setAutoCommit(false);    //把自动提交改为false
                 
                flag = dao.add(user);
                 
                connection.commit();                //提交事务
                connection.setAutoCommit(true);     //事物提交后把自动提交重新改为true
            catch (SQLException e) {
                e.printStackTrace();
            }
             
            DBUtil.closeConnection();
             
            System.out.println("add user result:" + flag);
        }
    }

     测试类不变,这样子,dao层的代码就更简洁了,同时也可以在service层中添加事务管理,也免去了多余的代码。

  • 相关阅读:
    数据库期末考试复习
    函数 初识
    文件操作
    深浅copy 和 集合
    数据编码补充
    字典的增删改查和嵌套
    面试题 和 python 2与3的期区别
    英文练习
    初识数据类型
    测试基础-系统测试(2)
  • 原文地址:https://www.cnblogs.com/night-wind/p/3877705.html
Copyright © 2011-2022 走看看