JavaWeb의 데이터베이스 트랜잭션 작업
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();
//
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.