Mybatis学习--9.Web项目中使用Mybatis
在WEB项目中使用MyBatis(以银行转账业务为例)
使用maven新建项目,在pom文件中将打包方式改为war,并重载(reload)项目。在pom文件中引入相关依赖
编写mybatis配置文件及logback配置文件:mybatis-config.xml,XxxMapper.xml,logback.xml
右键项目,找到openMouduleSettings。双击红色路径,这一步是在项目中引入web框架
在webapp目录下新建一个html文件(当作欢迎页使用),编写前端代码。项目逻辑:从前往后
编写后端代码
采用三层架构
建包:web(表现层)、service(业务层)、dao(可持久层)、util(工具包)、exceptions(异常包)、pojo(javaBean)
在web包下创建Servlet类,接收前端用户提交的数据,并调用相关业务方法。于此同时,编写pojo类
package com.deng.bank.web; import com.deng.bank.exceptions.moneyNotEnoughException; import com.deng.bank.exceptions.transferException; import com.deng.bank.service.AccountService; import com.deng.bank.service.impl.AccountServiceIm; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @WebServlet("/transfer") public class AccountServlet extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //get data from page String fromActno = request.getParameter("fromActno"); String toActno = request.getParameter("toActno"); Double money = Double.parseDouble(request.getParameter("money")); AccountService accountService = new AccountServiceIm(); try { accountService.transfer(fromActno,toActno,money); response.sendRedirect(request.getContextPath() + "/Success.html"); } catch (moneyNotEnoughException e) { response.sendRedirect(request.getContextPath() + "/Error1.html"); } catch (transferException e) { response.sendRedirect(request.getContextPath() + "/Error2.html"); }catch(Exception e){ response.sendRedirect(request.getContextPath() + "/Error2.html"); } } }
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
* 层与层之间通过接口交互。在service包和dao包下建立接口,并创建相应的子类实现该接口
* 
* 业务层调用dao层接口获取数据库连接,进行相应业务逻辑代码的编写
* ```java
package com.deng.bank.service.impl;
import com.deng.bank.dao.AccountDao;
import com.deng.bank.dao.impl.AccountDaoIm;
import com.deng.bank.exceptions.moneyNotEnoughException;
import com.deng.bank.exceptions.transferException;
import com.deng.bank.pojo.Account;
import com.deng.bank.service.AccountService;
import com.deng.bank.utils.SqlSessionUtil;
import org.apache.ibatis.session.SqlSession;
public class AccountServiceIm implements AccountService {
private AccountDao accountDao = new AccountDaoIm();
public void transfer(String fromActno,String toActno,Double money) throws moneyNotEnoughException, transferException {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
Account fromAct = accountDao.select(fromActno);
if(fromAct.getBalance() < money){
throw new moneyNotEnoughException("余额不足");
}else{
Account toAct = (Account)accountDao.select(toActno);
fromAct.setMoney(fromAct.getBalance() - money);
toAct.setMoney(toAct.getBalance() + money);
int count = accountDao.update(fromAct);
String str = null;
str.toString();
count += accountDao.update(toAct);
if(count != 2){
throw new transferException("转账失败,未知错误");
}
sqlSession.commit();
}
SqlSessionUtil.close();
}
}
如果我们在dao层进行事务管理,那么当业务层25-26行出现类似情况的异常时,本来应该终止转账,但由于我们将事务设置在dao层,那么fromAct账户的金额会发生改变,而toAct账户的金额却不会改变,相当于有一笔钱不翼而飞,这对银行来说是致命的错误。因此我们需要将事务管理设置在业务层。我们之前的做法是:每执行一次数据库CRUD操作就需要创建一个SqlSession对象,这显然无法做到原子性。
因此我们引入ThreadLocal对象,将SqlSession对象和当前线程绑定,从而实现事务的原子性
package com.deng.bank.utils; import org.apache.ibatis.io.Resources; import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; import java.io.IOException; public class SqlSessionUtil { private static SqlSessionFactory sqlSessionFactory; static{ try { sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml")); } catch (IOException e) { e.printStackTrace(); } } private static ThreadLocal<SqlSession> local = new ThreadLocal<>(); public static SqlSession getSqlSession(){ SqlSession sqlSession = local.get(); if(sqlSession == null){ sqlSessionFactory.openSession(); } return sqlSession; } public static void close(){ SqlSession sqlSession = local.get(); if (sqlSession!=null) { sqlSession.close(); local.remove(); } } }
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 dch'blog!