jdbc封装+自动手动事务无缝切换+简易连接池

401 阅读2分钟

dao层写法

 public ArrayList<User> selectAll() throws Exception {
 ​
     String sql = "select id,name,password,image from mall_user";
     ArrayList<User> list = new ArrayList<User>();
 ​
     // 如果执行了begin()函数,这里获取的是线程独有的连接,需要手动回滚提交
     // 否则要那一条单独的连接用于自动
     Connection conn = Connector.getConnection();
 ​
     PreparedStatement ps = conn.prepareStatement(sql);
     ResultSet res = ps.executeQuery();
     
     while (res.next()) {
         int id = res.getInt("id");
         String name = res.getString("name");
         String password = res.getString("password");
         String image = res.getString("image");
         list.add(new User(id, name, password, image));
     }
     // 如果执行了begin()函数,这里什么都不做
     // 否则直接在这里释放连接到连接池
     Connector.autoFreeConnection(conn);
 ​
     return list;
 }

自动事务:

 try {
     userdao.selectByName(username);
 } catch (Exception e) {
     // log...
 }

手动事务:

 try {
     Connector.begin();// 开启事务
     userdao.insert(user1);
     productdao.update(p1);
     Connector.commit();// 关闭事务
 } catch (Exception e) {
     Connector.rollback(); // 事务回滚
     //log...
 }

封装:

 import java.sql.*;
 import java.util.concurrent.ArrayBlockingQueue;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.logging.Logger;
 ​
 import com.hour.mall.config.SqlConfig;
 ​
 public class Connector {
 ​
     static Logger log = Logger.getLogger(Connector.class.getName());
 ​
     static final String JDBC_DRIVER = SqlConfig.MySql_JDBC_DRIVER;
     static final String DB_URL = SqlConfig.DB_URL;
     static final String USER = SqlConfig.USER;
     static final String PASS = SqlConfig.PASS;
 ​
     static final int maxNum = 128;
     static AtomicInteger nowActive = new AtomicInteger(0);
     static BlockingQueue<Connection> freeConnectionPool = new ArrayBlockingQueue<Connection>(128);
 ​
     // 用于手动提交事务
     static ThreadLocal<Connection> nowConnectionLocal = new ThreadLocal<>();
     // 当前是手动还是自动
     static ThreadLocal<Boolean> autoLocal = new ThreadLocal<>();
 ​
     // 获取连接
     public static Connection getConnection() throws Exception {
         if (autoLocal.get() == null) {
             // 自动提交就不用ThreadLocal了
             log.info("当前事务:自动提交");
             return doConnection();
         } else {
             // 手动提交用ThreadLocal,但是需要提前begin声明
             log.info("当前事务:手动提交");
             return nowConnectionLocal.get();
         }
     }
 ​
     // 声明手动提交事务
     public static void begin() throws Exception {
         log.info("手动提交事务已开启");
         nowConnectionLocal.set(doConnection());
         nowConnectionLocal.get().setAutoCommit(false);
         autoLocal.set(false);
     }
 ​
     // 手动提交
     public static void commit() throws Exception {
         if (nowConnectionLocal.get() != null) {
             nowConnectionLocal.get().commit();
             nowConnectionLocal.get().setAutoCommit(true);
             log.info("手动提交事务已提交");
             freeConnection(nowConnectionLocal.get());
             nowConnectionLocal.remove();
             autoLocal.set(true);
         } else {
             log.info("手动提交事务提交失败,当前无事务");
         }
     }
 ​
     // 手动回滚
     public static void rollback() throws Exception {
         if (nowConnectionLocal.get() != null) {
         try {
                nowConnectionLocal.get().rollback();
                nowConnectionLocal.get().setAutoCommit(true);
                log.info("手动提交事务已回滚");
                freeConnection(nowConnectionLocal.get());
                nowConnectionLocal.remove();
                autoLocal.set(true);
            } catch (Exception e) {
                log.info("手动提交事务回滚失败");
            }
         } else {
             log.info("手动提交事务回滚失败,当前无事务");
         }
     }
 ​
     /**
      * 连接放入空闲区
      */
     public static void autoFreeConnection(Connection connection) {
         if (autoLocal.get()) {
             freeConnectionPool.add(connection);
             nowActive.getAndDecrement();
             log.info("自动事务连接已自动释放");
         }
     }
 ​
     /**
      * 断开连接
      */
     public static void closeConnection() {
         for (Connection c : freeConnectionPool) {
             try {
                 c.close();
             } catch (SQLException e) {
                 System.out.println(c + "关闭失败");
             }
         }
     }
 ​
     /**
      * 放入空闲区连接
      */
     private static void freeConnection(Connection connection) {
         if (connection != null) {
             freeConnectionPool.add(connection);
             nowActive.getAndDecrement();
         }
     }
 ​
     /**
      * 
      * 
      * @throws ClassNotFoundException
      * @throws SQLException
      * @throws InterruptedException
      */
     public static Connection doConnection()
             throws ClassNotFoundException, SQLException, InterruptedException {
 ​
        Connection connection = null;

        if(nowActive.get() < maxNum) {   
            // 注册 JDBC 驱动
            Class.forName(JDBC_DRIVER);
            // 打开链接
            connection = DriverManager.getConnection(DB_URL, USER, PASS);

            nowActive.getAndIncrement();

            return connection;
        }
        
        while((connection = freeConnectionPool.poll()) == null){
        }   
        
        return connection;
 }