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