使用动态代理实现数据库事务
Posted kzd666
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用动态代理实现数据库事务相关的知识,希望对你有一定的参考价值。
数据库sql:
1 create table T_USER
2 (
3 USER_ID VARCHAR(10) not null,
4 USER_NAME VARCHAR(30) not null,
5 PASSWORD VARCHAR(20) not null,
6 CONTACT_TEL VARCHAR(30),
7 EMAIL VARCHAR(30),
8 CREATE_DATE DATE,
9 constraint P_KEY_1 primary key (USER_ID)
10 );
11
12 insert into t_user(user_id, user_name, password) values(‘root‘, ‘系统管理员‘, ‘root‘);
ConnectionManager.java(数据库连接管理)
1 package dynamicProxyTransaction; 2 3 import java.sql.Connection; 4 import java.sql.DriverManager; 5 import java.sql.SQLException; 6 7 public class ConnectionManager { 8 private ConnectionManager() { 9 } 10 11 private static ThreadLocal<Connection> threadConn = new ThreadLocal<Connection>(); 12 13 // 获取数据库连接 14 public static Connection getConnection() { 15 Connection conn = threadConn.get(); 16 if (conn == null) { 17 try { 18 Class.forName("com.ibm.db2.jcc.DB2Driver"); 19 conn = DriverManager.getConnection( 20 "jdbc:db2://127.0.0.1:50000/DRP", "db2admin", "619100"); 21 } catch (ClassNotFoundException e) { 22 e.printStackTrace(); 23 } catch (SQLException e) { 24 e.printStackTrace(); 25 } 26 threadConn.set(conn); 27 } 28 return conn; 29 } 30 31 // 设置事务手动提交 32 public static void benigTransction(Connection conn) { 33 try { 34 if (conn != null) { 35 if (conn.getAutoCommit()) { 36 conn.setAutoCommit(false); 37 } 38 } 39 } catch (SQLException e) { 40 e.printStackTrace(); 41 } 42 } 43 44 // 提交事务 45 public static void endTransction(Connection conn) { 46 try { 47 if (conn != null) { 48 if (!conn.getAutoCommit()) { 49 conn.commit(); 50 } 51 } 52 } catch (SQLException e) { 53 e.printStackTrace(); 54 } 55 } 56 57 // 设置Connection的原始状态 58 public static void recoverTransction(Connection conn) { 59 try { 60 if (conn != null) { 61 if (conn.getAutoCommit()) { 62 conn.setAutoCommit(false); 63 } else { 64 conn.setAutoCommit(true); 65 } 66 } 67 } catch (SQLException e) { 68 e.printStackTrace(); 69 } 70 } 71 72 // 发生异常回滚事务 73 public static void rollback(Connection conn) { 74 try { 75 if (conn != null) { 76 conn.rollback(); 77 } 78 } catch (SQLException e) { 79 e.printStackTrace(); 80 } 81 } 82 83 // 关闭连接,并将其从当前线程删除 84 public static void close() { 85 Connection conn = threadConn.get(); 86 if (conn != null) { 87 try { 88 conn.close(); 89 conn = null; 90 threadConn.remove(); 91 } catch (SQLException e) { 92 e.printStackTrace(); 93 } 94 } 95 } 96 }
User.java(实体类)
1 package dynamicProxyTransaction; 2 3 import java.util.Date; 4 5 public class User { 6 // 用户ID 7 private String id; 8 // 用户名称 9 private String name; 10 // 登陆密码 11 private String password; 12 // 联系电话 13 private String contact_tel; 14 // 电子邮件 15 private String email; 16 // 用户创建日期 17 private Date create_date; 18 19 public String getId() { 20 return id; 21 } 22 23 public void setId(String id) { 24 this.id = id; 25 } 26 27 public String getName() { 28 return name; 29 } 30 31 public void setName(String name) { 32 this.name = name; 33 } 34 35 public String getPassword() { 36 return password; 37 } 38 39 public void setPassword(String password) { 40 this.password = password; 41 } 42 43 public String getContact_tel() { 44 return contact_tel == null ? "" : contact_tel; 45 } 46 47 public void setContact_tel(String contact_tel) { 48 this.contact_tel = contact_tel; 49 } 50 51 public String getEmail() { 52 return email == null ? "" : email; 53 } 54 55 public void setEmail(String email) { 56 this.email = email; 57 } 58 59 public Date getCreate_date() { 60 return create_date; 61 } 62 63 public void setCreate_date(Date create_date) { 64 this.create_date = create_date; 65 } 66 }
UserDAO.java(用户相关的数据库操作)
1 package dynamicProxyTransaction; 2 3 import java.sql.SQLException; 4 5 public interface UserDAO { 6 public User selUser(String id ) throws SQLException ; 7 }
UserDAOImpl.java(UserDAO实现类)
1 package dynamicProxyTransaction; 2 3 import java.sql.Connection; 4 import java.sql.PreparedStatement; 5 import java.sql.ResultSet; 6 import java.sql.SQLException; 7 8 public class UserDAOImpl implements UserDAO { 9 @Override 10 public User selUser(String id) throws SQLException { 11 ResultSet resu = null; 12 String sql = "SELECT * FROM DB2ADMIN.T_USER WHERE USER_ID = ?"; 13 Connection conn = ConnectionManager.getConnection(); 14 PreparedStatement pstat = conn.prepareStatement(sql); 15 User user = null; 16 try { 17 pstat.setString(1, id); 18 resu = pstat.executeQuery(); 19 if (resu.next()) { 20 user = getUser(resu); 21 } 22 } finally { 23 if (resu != null) { 24 resu.close(); 25 } 26 if (pstat != null) { 27 pstat.close(); 28 } 29 } 30 return user; 31 } 32 // 获取用户 33 private User getUser(ResultSet resu) throws SQLException { 34 User user = new User(); 35 user.setId(resu.getString("USER_ID")); 36 user.setName(resu.getString("USER_NAME")); 37 user.setPassword(resu.getString("PASSWORD")); 38 user.setContact_tel(resu.getString("CONTACT_TEL")); 39 user.setEmail(resu.getString("EMAIL")); 40 user.setCreate_date(resu.getTimestamp("CREATE_DATE")); 41 return user; 42 } 43 }
UserManager.java(用户管理功能定义)
1 package dynamicProxyTransaction; 2 3 public interface UserManager { 4 public User findUser(String id ) throws Exception ; 5 }
UserManagerImpl.java(UserManager实现类)
1 package dynamicProxyTransaction; 2 3 import java.sql.SQLException; 4 5 public class UserManagerImpl implements UserManager { 6 // 这个和我以前写的不一样: 我都是写在每个方法中,写成属性应该好一点,减少创建对象的次数 7 private UserDAO userDAO = null; 8 9 public UserManagerImpl() { 10 userDAO = new UserDAOImpl(); 11 } 12 13 public User findUser(String id) throws SQLException { 14 return userDAO.selUser(id); 15 } 16 }
TransactionProxy.java(代理实现)
1 package dynamicProxyTransaction; 2 3 import java.lang.reflect.InvocationHandler; 4 import java.lang.reflect.InvocationTargetException; 5 import java.lang.reflect.Method; 6 import java.lang.reflect.Proxy; 7 import java.sql.Connection; 8 9 public class TransactionProxy implements InvocationHandler { 10 private Object obj = null; 11 12 // obj:需要代理的类 13 public Object newProxyInstance(Object obj) { 14 this.obj = obj; 15 return Proxy.newProxyInstance(this.obj.getClass().getClassLoader(), 16 this.obj.getClass().getInterfaces(), this); 17 } 18 19 @Override 20 public Object invoke(Object proxy, Method method, Object[] args) 21 throws Throwable { 22 // 用于接收参数 23 Object param = null; 24 // 如果是以下方法开头,则代理事务 25 if (method.getName().startsWith("add") 26 || method.getName().startsWith("modify") 27 || method.getName().startsWith("find") 28 || method.getName().startsWith("del")) { 29 Connection conn = ConnectionManager.getConnection(); 30 try { 31 // 手动提交事务 32 ConnectionManager.benigTransction(conn); 33 param = method.invoke(obj, args); 34 // 提交事务 35 ConnectionManager.endTransction(conn); 36 } catch (Exception e) { 37 // 回滚事务 38 ConnectionManager.rollback(conn); 39 if (e instanceof InvocationTargetException) { 40 InvocationTargetException inv = (InvocationTargetException) e; 41 throw inv.getTargetException(); 42 } else { 43 throw new Exception("操作失败!"); 44 } 45 } finally { 46 // 还原状态 47 ConnectionManager.recoverTransction(conn); 48 ConnectionManager.close(); 49 } 50 } 51 return param; 52 } 53 }
Test.java(测试)
1 package dynamicProxyTransaction; 2 3 public class Test { 4 public static void main(String[] args) throws Exception { 5 TransactionProxy transctionProxy = new TransactionProxy(); 6 7 // //产生代理对象 8 UserManager userManager = (UserManager) transctionProxy 9 .newProxyInstance(new UserManagerImpl()); 10 User user = userManager.findUser("root"); 11 System.out.println("用户名:" + user.getName()); 12 } 13 14 }
以上是关于使用动态代理实现数据库事务的主要内容,如果未能解决你的问题,请参考以下文章
Spring声明式事务的实现方式选择(JDK动态代理与cglib)