众所周知,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层中添加事务管理,也免去了多余的代码。

JDBC化繁为简的更多相关文章

  1. Java数据库连接技术——JDBC

    大家好,今天我们学习了Java如何连接数据库.之前学过.net语言的数据库操作,感觉就是一通百通,大同小异. JDBC是Java数据库连接技术的简称,提供连接各种常用数据库的能力. JDBC API ...

  2. 玩转spring boot——结合AngularJs和JDBC

    参考官方例子:http://spring.io/guides/gs/relational-data-access/ 一.项目准备 在建立mysql数据库后新建表“t_order” ; -- ----- ...

  3. [原创]java使用JDBC向MySQL数据库批次插入10W条数据测试效率

    使用JDBC连接MySQL数据库进行数据插入的时候,特别是大批量数据连续插入(100000),如何提高效率呢?在JDBC编程接口中Statement 有两个方法特别值得注意:通过使用addBatch( ...

  4. JDBC MySQL 多表关联查询查询

    public static void main(String[] args) throws Exception{ Class.forName("com.mysql.jdbc.Driver&q ...

  5. JDBC增加删除修改

    一.配置程序--让我们程序能找到数据库的驱动jar包 1.把.jar文件复制到项目中去,整合的时候方便. 2.在eclipse项目右击"构建路径"--"配置构建路径&qu ...

  6. JDBC简介

    jdbc连接数据库的四个对象 DriverManager  驱动类   DriverManager.registerDriver(new com.mysql.jdbc.Driver());不建议使用 ...

  7. JDBC Tutorials: Commit or Rollback transaction in finally block

    http://skeletoncoder.blogspot.com/2006/10/jdbc-tutorials-commit-or-rollback.html JDBC Tutorials: Com ...

  8. FineReport如何用JDBC连接阿里云ADS数据库

    在使用FineReport连接阿里云的ADS(AnalyticDB)数据库,很多时候在测试连接时就失败了.此时,该如何连接ADS数据库呢? 我们只需要手动将连接ads数据库需要使用到的jar放置到%F ...

  9. JDBC基础

    今天看了看JDBC(Java DataBase Connectivity)总结一下 关于JDBC 加载JDBC驱动 建立数据库连接 创建一个Statement或者PreparedStatement 获 ...

随机推荐

  1. SpringCloudStream学习(三)RabbitMQ中的惰性队列

    ​ 从RabbitMQ 3.6.0之后,有了 Lazy Queues 的概念-一个会尽早的将队列中的内容移动到磁盘的队列,并且只有当消费者需要的时候,才会将它们加载到内存中 ​ 惰性队列设计的一个主要 ...

  2. 【华为云技术分享】MongoDB经典故障系列五:sharding集群执行sh.stopBalancer()命令被卡住怎么办?

    [摘要] MongoDB sharding集群执行sh.stopBalancer()命令时被卡住怎么办?别慌,华为云数据库来给您支招,收下这份方案指南,让您分分钟远离被自建MongoDB数据库支配的恐 ...

  3. [hdu4911]逆序对相关

    思路:由于只能交换相邻的数,所以每次最多减小1个逆序对(且如果存在逆序对那么肯定可以减小1个)!于是乎..就是统计逆序对的裸题了.树状数组或归并都行. #pragma comment(linker, ...

  4. 选择函数index_select

    书中(pytorch入门实战)讲:index_select(input, dim, index),指定维度dim上选取,未有示例. 查到相关资料后, import torch as t # 导入tor ...

  5. HDU 2007 (水)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2007 题目大意:给你段连续数字,让你求 all sum of (偶数2 )and all sum of ...

  6. 剑指Offer02之替换空格

    剑指Offer02之替换空格 题目描述 实现一个方法,将输入的字符串中的空格替换成%20. 例子如下 hello world --> hello%20world 代码实现 //方法一 采用Jav ...

  7. Apache 慢连接dos

    http://neue.v2ex.com/t/108717------不实用 http://www.blogjava.net/bukebushuo/articles/293776.html http: ...

  8. STM32 HAL库学习系列---定时器TIM 输入捕获功能

    基本方法 1.设置TIM2 CH1为输入捕获功能: 2.设置上升沿捕获: 3.使能TIM2 CH1捕获功能: 4.捕获到上升沿后,存入capture_buf[0],改为捕获下降沿: 5.捕获到下降沿后 ...

  9. 英语四六级模拟考试系统APP

    Android studio开发的.eclipse的SSM框架作为服务器后台.Mysql5.6. 我先上几张图吧. 需要源码可以留言给我.另外本人接外包或者有问题也可以问我.留言,我会看的.

  10. Java并发(4)

    java中的线程安全是什么: 就是线程同步的意思,就是当一个程序对一个线程安全的方法或者语句进行访问的时候,其他的不能再对他进行操作了,必须等到这次访问结束以后才能对这个线程安全的方法进行访问 什么叫 ...