事务示例之转账
1.创建数据库,填充数据:
数据库名称db_account,表名tb_account,插入几条数据。
2.配置数据库信息
在项目的WebContent/META-INF目录下创建一个context.xml文件。如图:
在context.xml文件中配置:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Resource name="jdbc/account" auth="Container" type="javax.sql.DataSource"
maxActive="100" maxIdle="30" maxWait="10000"
username="root" password="root" driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/db_account"/>
</Context>
1
2
3
4
5
6
7
这里采用的是Javaweb自带的DBCP配置,详细参考Javaweb配置常用的数据源配置
3.创建项目结构
如图:
AccountDao
public interface AccountDao {
/**
* 更新账户
* @param account
*/
public boolean updateAccount(Account account) throws SQLException;
/**
* 查找账户
* @param account
* @return
*/
public Account findAccountByName(String account);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
AccountDaoImpl
public class AccountDaoImpl implements AccountDao{
public AccountDaoImpl() {
}
@Override
public boolean updateAccount(Account account) {
Connection conn = ManagerThreadLocal.getConn();
if(conn==null){
throw new NullPointerException("Connection is null");
}
PreparedStatement ps = null;
try {
ps = conn.prepareStatement("update tb_account set money=? where name=?");
if(ps==null){
throw new NullPointerException("PreparedStatement is null");
}
ps.setDouble(1, account.getMoney());
ps.setString(2, account.getName());
int i = ps.executeUpdate();
return i>0;
} catch (SQLException e) {
e.printStackTrace();
}
return false;
}
@Override
public Account findAccountByName(String account) {
Connection conn = ManagerThreadLocal.getConn();
if(conn==null){
throw new NullPointerException("Connection is null");
}
Account a = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = conn.prepareStatement("select name,money from tb_account where name=?");
if(ps==null){
throw new NullPointerException("PreparedStatement is null");
}
ps.setString(1, account);
rs = ps.executeQuery();
if(rs==null){
throw new NullPointerException("ResultSet is null");
}
if(rs.next()){
a = new Account();
a.setName(rs.getString(1));
a.setMoney(rs.getDouble(2));
return a;
}
} catch (SQLException e) {
e.printStackTrace();
}
return a;
}
}
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
60
61
62
63
64
65
66
67
68
69
Account
public class Account {
private int id;
private String name;
private double money;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
@Override
public String toString() {
return "Account [id=" + id + ", name=" + name + ", money=" + money + "]";
}
}
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
AccountService
public interface AccountService {
/**
* 转账
* @param fromName
* @param toName
* @param money
*/
public void transfer(String fromName,String toName,double money);
}
1
2
3
4
5
6
7
8
9
AccountServiceImpl
public class AccountServiceImpl implements AccountService{
@Override
public void transfer(String fromName, String toName, double money) {
AccountDao accountDao = new AccountDaoImpl();
Account fromAccount = accountDao.findAccountByName(fromName);
if(fromAccount==null){
throw new RuntimeException("你的账户不存在");
}
if(money > fromAccount.getMoney()){
throw new RuntimeException("你的账户的钱不够");
}
fromAccount.setMoney(fromAccount.getMoney() - money);
Account toAccount = accountDao.findAccountByName(toName);
if(toAccount==null){
throw new RuntimeException("对方的账户不存在");
}
toAccount.setMoney(toAccount.getMoney() + money);
//开启事务
ManagerThreadLocal.startTransaction();
try {
accountDao.updateAccount(fromAccount);
//int i = 10/0; //测试事务代码
accountDao.updateAccount(toAccount);
//提交事务
ManagerThreadLocal.commit();
} catch (SQLException e) {
//事务回滚
ManagerThreadLocal.rollback();
e.printStackTrace();
}finally {
ManagerThreadLocal.close();
}
}
}
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
TransferServlet
@WebServlet({ "/TransferServlet", "/transfer" })
public class TransferServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public TransferServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
AccountService accountService = new AccountServiceImpl();
accountService.transfer("10010", "10000", 100);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
ManagerThreadLocal
public class ManagerThreadLocal {
private static ThreadLocal<Connection> tl = new ThreadLocal<>();
private static Connection getConnection(){
Connection conn = null;
try {
Context context = new InitialContext();
DataSource dataSource = (DataSource) context.lookup("java:/comp/env/jdbc/account");
conn = (Connection) dataSource.getConnection();
} catch (SQLException e) {
e.printStackTrace();
} catch (NamingException e) {
e.printStackTrace();
}
return conn;
}
public static Connection getConn(){
Connection conn = null;
conn = tl.get();
if(conn==null){
conn = getConnection();
tl.set(conn);
}
return conn;
}
public static void startTransaction(){
try {
getConn().setAutoCommit(false);
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void commit(){
try {
getConn().commit();
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void rollback(){
try {
getConn().rollback();
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void close(){
try {
getConn().close();
tl.remove();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
---------------------
【转载】
作者:张行之
来源:CSDN
原文:https://blog.csdn.net/qq_33689414/article/details/63251216
版权声明:本文为博主原创文章,转载请附上博文链接!
|
|