JavaWeb의 데이터베이스 트랜잭션 작업

4923 단어
JDBC로 데이터베이스를 조작하는 데는 커넥션 클래스의 setautoCommit(false) 방법을 사용하면 업무를 열 수 있고,commit() 방법으로 업무를 제출할 수 있다.
3층 구조의 디자인 모델로 인해 사무의 논리는 반드시 서비스 층에 있어야 하고dao층은 간단한 CRUD 조작만 제공하기 때문에 서비스가 연결을 가져와 사무를 열어야 한다. 이 연결을 서비스 층에 전달하여 조작한 후에 서비스 층에서 사무를 제출해야 한다.
Connection을 dao층에 전달하면 dao층 방법(또는 구조 함수)을 호출할 때 매개 변수 형식으로 전달할 수 있다. 그러나 이렇게 하면 dao층의 방법 서명을 오염시킬 뿐만 아니라 여러 층의 매개 변수 전달에 대해 방법이 길고 구리게 보일 수 있다. 다음은 ThreadLocal 용기로 매개 변수를 전달하는 방법이 훨씬 우아해 보인다.
①Tomcat 서버에 대해 모든 http 요청은 하나의 라인으로 분배되어 처리됩니다. 처리된 라인은 새로운 라인일 수도 있고 라인 탱크에서 얻을 수도 있습니다.하나의 요청은 같은 라인에서 이루어진다.
② ThreadLocal은 현재 스레드를 키로 저장하고 현재 스레드를 키로 해당하는 대상을 꺼낼 수 있습니다.
같은 라인에서 우리는 서비스 층에서 하나의 Connection을 켜서 ThreadLocal에 병존하고 코드가dao층의 업데이트 방법으로 실행될 때 ThreadLocal의 Connection을 가져옵니다. 이 Connection으로 데이터베이스를 조작합니다. 방법은 서비스 층으로 돌아간 후 ThreadLocal에서 Connection을 가져옵니다. 업무를 제출하고 ThreadLocal 용기를 지웁니다.
코드는 다음과 같습니다.
  1.dao 레이어 코드:
package com.hao.utils;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

public class DaoUtils {
    private static DataSource ds;
    private static ThreadLocal connectionThreadLocal = new ThreadLocal<>();

    static {
        try {
            Context initCtx = new InitialContext();
            Context envCtx = (Context) initCtx.lookup("java:comp/env");
            ds = (DataSource) envCtx.lookup("jdbc/EmployeeDB");
        } catch (NamingException e) {
            throw new ExceptionInInitializerError(e);
        }
    }
//    ,                ,   service    
    public static void startTransaction() {
        try {
            Connection conn = ds.getConnection();
            conn.setAutoCommit(false);
            connectionThreadLocal.set(conn);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    //      ,        ,   dao   
    public static Connection getTransactionConnection() {
        return connectionThreadLocal.get();
    }

    //    , Connection       ,   service   
    public static void commitTransaction() {
        try {
            Connection conn = connectionThreadLocal.get();
            conn.commit();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            //  connectionThreadLocal    ,             ,              
            connectionThreadLocal.remove();
        }
    }

}
package com.hao.dao;

import com.hao.domain.Account;
import com.hao.utils.DaoUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;

import java.sql.SQLException;

public class AccountDao {
    private QueryRunner qr = new QueryRunner();

    public void add(Account account) {
        String sql = "insert into account(id,name,money) values(?,?,?)";
        try {
            qr.update(sql, account.getId(), account.getName(), account.getMoney());
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    public void delete(String id) {
        String sql = "delete from account where id = ?";
        try {
            qr.update(sql, id);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    public void update(Account account) {
        String sql = "update account set name=?,money=? where id=?";
        try {
            //            
            qr.update(DaoUtils.getTransactionConnection(), sql, account.getName(), account.getMoney(), account.getId());
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }

    public Account find(String id) {
        String sql = "select name,money from account where id=?";
        try {
            Account account = qr.query(sql, new BeanHandler(Account.class), id);
            account.setId(id);
            return account;
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}

 2.서비스 계층 코드:
package com.hao.service;

import com.hao.dao.AccountDao;
import com.hao.domain.Account;
import com.hao.utils.DaoUtils;

public class BusinessService {
    public void transfer(String sourceId, String targetId, double money) {
        //    
        DaoUtils.startTransaction();
        //    
        AccountDao dao = new AccountDao();
        Account sourceAccount = dao.find(sourceId);
        sourceAccount.setMoney(sourceAccount.getMoney() - money);
        dao.update(sourceAccount);
        Account targetAccount = dao.find(targetId);
        targetAccount.setMoney(targetAccount.getMoney() + money);
        dao.update(targetAccount);
        //    
        DaoUtils.commitTransaction();
        //               
    }
}

좋은 웹페이지 즐겨찾기