Mybatis实现转账

前期准备

数据库准备

在ssm数据库下通过查询建立account表

导入jar包

准备全局配置文件mybatis.xml文件

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

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>

<typeAliases>
<package name="com.bjsxt.pojo"/> <!-- 起别名 方便在配置的xml里面直接返回值就可以只写类名-->
</typeAliases>

<environments default="default">
<environment id="default">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/ssm"/>
<property name="username" value="root"/>
<property name="password" value="njdxrjgc7777777."/>
</dataSource>
</environment>
</environments>

<mappers>
<mapper resource="com/bjsxt/mapper/AccountMapper.xml"/> <!-- 直接调用配置文件 执行sql语句 -->
</mappers>

</configuration>

准备pojo包的实体类Account

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

public class Account {
private int id;
private String accNo;
private int password;
private String name;
private double balance;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAccNo() {
return accNo;
}
public void setAccNo(String accNo) {
this.accNo = accNo;
}
public int getPassword() {
return password;
}
public void setPassword(int password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
}

准备mapper包下的AccountMapper.xml文件

通过分析我们要有三个任务:分别是写在三个select标签下完成对应任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.bjsxt.mapper.AccountMapper">
<!-- 根据帐号和密码查询账户信息 -->
<select id="selByAccnoPwd" resultType="account" parameterType="account"> //id就是此方法名称 resultType就是返回值类型
select * from account where accno=#{accNo} and password=#{password}
</select>

<!-- 根据帐号和姓名查询账户信息 -->
<select id="selByAccnoName" resultType="account" parameterType="account">
select * from account where accno=#{accNo} and name=#{name}
</select>

<!-- 根据accNo修改账户余额 -->
<update id="updBalanceByAccno" parameterType="account">
update account set balance=balance+#{balance} where accno=#{accNo}
</update>

</mapper>

准备serive包下的AccountService接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public interface AccountService {

//帐号和密码不匹配状态码
int ACCOUNT_PASSWORD_NOT_MATCH=1;

//余额不足
int ACCOUNT_BALANCE_NOT_ENOUGH=2;
//账户姓名不匹配
int ACCOUNT_NAME_NOT_MATCH=3;
//转账失败
int ERROR=4;
//转账成功
int SUCCESS=5;

//转账功能
int transfer(Account accIn,Account accOut) throws IOException;

}

准备1.0版本的serviceimpl包

准备思路:

1. 先判断账号和密码是否匹配 (调用方法查sql语句)
    2. 然后判断是否有足够转账金额 (判断账号密码查信息返回给account类 然后调用balance去判断是否足够)
        3. 判断收款人账号和名字是否正确 
            4. 然后进行转账交易 (调用方法 一个减少一个增加)
                5. 判断是不是成功
                    5.1 成功就session.commit()提交 --  session.close()关闭  -- 返回成功的结果值
                    5.2 失败就session.rollback()回滚 --session.close()关闭 -- 返回失败的结果值 

实现类实现初级1.0事务:

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

public class AccountServiceImpl implements AccountService {
@Override
public int transfer(Account accIn, Account accOut) throws IOException {

//固定的三行生产出session
InputStream is = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession session = factory.openSession();

//先判断帐号和密码是否匹配
Account accOutSelect = session.selectOne("com.bjsxt.mapper.AccountMapper.selByAccnoPwd",accOut); //根据账号和密码查询
if(accOutSelect!=null){ //账号和密码匹配
if(accOutSelect.getBalance()>=accOut.getBalance()) { //余额够
Account accInSelect = session.selectOne("com.bjsxt.mapper.AccountMapper.selByAccnoName",accIn); //根据账号和姓名查询
if(accInSelect!=null) {
accOut.setBalance(-accOut.getBalance()); //set设置一下为负数
int index=session.update("com.bjsxt.mapper.AccountMapper.updBalanceByAccno",accOut); //如果传的是accOut 就需要的是扣除交易额
index += session.update("com.bjsxt.mapper.AccountMapper.updBalanceByAccno",accIn); //转账过去
if(index==2) {
session.commit(); //成功就提交
session.close();
return SUCCESS;
}else {
session.rollback(); //失败就要回滚
session.close();
return ERROR;
}
}else {
return ACCOUNT_NAME_NOT_MATCH; //账号和姓名不匹配
}
}else {
return ACCOUNT_BALANCE_NOT_ENOUGH; //余额不足
}
}else{
return ACCOUNT_PASSWORD_NOT_MATCH; // 账号和密码 不匹配
}

}
}

准备servlet包下的TransferServlet类

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

@WebServlet("/transfer")
public class TransferServlet extends HttpServlet {

//面向接口编程
private AccountService accService = new AccountServiceImpl();

@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//需要使用到中文
req.setCharacterEncoding("utf-8");

//获取转账人的信息
Account accOut = new Account();
accOut.setAccNo(req.getParameter("accOutAccNo"));
accOut.setPassword(Integer.parseInt(req.getParameter("accOutPassword")));
accOut.setBalance(Double.parseDouble(req.getParameter("accOutBalance")));

//获取收款人信息
Account accIn =new Account();
accIn.setAccNo(req.getParameter("accInAccNo"));
accIn.setName(req.getParameter("accInName"));

//通过面向接口编程 调用转账功能
int index = accService.transfer(accIn, accOut);

if(index==AccountService.SUCCESS) //转账成功的返回值和 service的静态success对比
{
resp.sendRedirect("/bank/show"); //成功跳转到展示页面
}
else
{
HttpSession session = req.getSession();
session.setAttribute("code", index); // 获得状态码
resp.sendRedirect("/bank/error/error.jsp"); //新建的error文件下的error.jsp页面
}

}
}

准备登陆/失败/转账查询的页面

log显示成功界面

1
2
3
<body>
成功的log.jsp
</body>

index主页面界面

1
2
3
4
5
6
7
8
9
10
11
12
<body>

<form action="transfer" method="post"> //写一个页表 -- servlet类
转账账户:<input type="text" name="accOutAccNo"/><br/>
密码:<input type="password" name="accOutPassword"/><br/>
金额:<input type="text" name="accOutBalance"/><br/>
收款帐号:<input type="text" name="accInAccNo"/><br/>
收款姓名:<input type="text" name="accInName"/><br/>
<input type="submit" value="转账"/>
</form>

</body>

error错误界面

1
2
3
4
5
<body>
对不起操作失败:<br/>
错误原因:
${sessionScope.code} //通过jsp方式传出错误的原因对应的service的数字
</body>

准备log4j (查错)

带入jar包和配置文件log4j.properties

1
2
3
4
5
6
7
8
9
10
11
12
13
log4j.rootCategory=ERROR, CONSOLE ,LOGFILE   //显示设置error去查找错误

log4j.logger.com.bjsxt.mapper=DEBUG //给这个包添加log4j文件

log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%C %d{YYYY-MM-dd hh:mm:ss} %m %n

log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=E:/my.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%m %n

全局配置文件中配置log4j

1
2
3
<settings>
<setting name="logImpl" value="LOG4J"/>
</settings>

执行结果


日志记录

创建表log

1
2
3
4
5
6
create table log(
id int(10) primary key auto_increment,
accout varchar(18),
accin varchar(8),
money double
);

新增log实体类

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
public class Log {
private int id;
private String accIn;
private String accOut;
private double money;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAccIn() {
return accIn;
}
public void setAccIn(String accIn) {
this.accIn = accIn;
}
public String getAccOut() {
return accOut;
}
public void setAccOut(String accOut) {
this.accOut = accOut;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
}

新增关于log表的配置xml文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bjsxt.mapper.LogMapper">

<insert id="insLog" parameterType="log">
insert into log values(default,#{accOut},#{accIn},#{money}) //添加数据
</insert>

<select id="selByPage" parameterType="map" resultType="log"> //分页
select * from log limit #{pageStart},#{pageSize}
</select>

<select id="selCount" resultType="long"> //查询所有
select count(*) from log
</select>

</mapper>

在serviceimpl实现类添加

1
2
3
4
5
6
7
8

//在已经转账成功 index==2之后添加

Log log=new Log();
log.setAccIn(accIn.getAccNo()); //取出来所有信息然后添加到log实体类对象
log.setAccOut(accOut.getAccNo());
log.setMoney(accIn.getBalance());
session.insert("com.bjsxt.mapper.LogMapper.insLog",log); //转账成功就添加到log表里面

日志文件显示转账信息(log4j)

1
2
3
4
5
6
//1. 要在log4j配置文件内更改:
log4j.appender.LOGFILE.layout.ConversionPattern=%m %n //最后要是%m %n

//2. 在刚才的实现类代码下添加日志文件记录(同时将log4j第一行的异常给一个info才可以显示)
Logger logger=Logger.getLogger(AccountServiceImpl.class);
logger.info(log.getAccOut()+"给"+log.getAccOut()+"在"+new Date().toLocaleString()+"转了"+log.getMoney()); //在log4j的五种异常中选info异常

分页展示功能

mapper包xml里面添加分页功能的sql语句

1
2
3
4
5
6
7
<select id="selByPage" parameterType="map" resultType="log">  //分页
select * from log limit #{pageStart},#{pageSize}
</select>

<select id="selCount" resultType="long"> //查询所有
select count(*) from log
</select>

添加分页显示的实体类

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
public class PageInfo {
private int pageSize;
private int pageNumber;
private long total;
private List<?> list;
public int getPageSize() {
return pageSize;
}
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
}
public int getPageNumber() {
return pageNumber;
}
public void setPageNumber(int pageNumber) {
this.pageNumber = pageNumber;
}
public long getTotal() {
return total;
}
public void setTotal(long total) {
this.total = total;
}
public List<?> getList() {
return list;
}
public void setList(List<?> list) {
this.list = list;
}

}

service层接口实现方法

1
2
3
4
5
6
7
8
9
public interface LogService  {
/**
* 分页显示
* @param pageSize
* @param pageNumber
* @return
*/
PageInfo showPage(int pageSize,int pageNumber) throws IOException;
}

service实现类

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

public class LogServiceImpl implements LogService {

@Override
public PageInfo showPage(int pageSize, int pageNumber) throws IOException {

//固定三行
InputStream is = Resources.getResourceAsStream("mybatis.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession session = factory.openSession();

Map<String,Object> param = new HashMap<>();
param.put("pageStart",pageSize*(pageNumber-1)); //获取当前页要从第几个开始
param.put("pageSize", pageSize); //获取一页展示几个


List<Log> list = session.selectList("com.bjsxt.mapper.LogMapper.selByPage",param); //param是一个map 创建一个map 将最后的map集合的值给log实体类
long count = session.selectOne("com.bjsxt.mapper.LogMapper.selCount"); //查询总数

PageInfo pi = new PageInfo(); //分页类实现对象(四个属性)
pi.setList(list);
pi.setPageNumber(pageNumber);
pi.setPageSize(pageSize);
pi.setTotal(count%pageSize==0?count/pageSize:count/pageSize+1); //算出来总共几个几页

return pi;

}
}

准备servlet类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

@WebServlet("/show")
public class ShowServlet extends HttpServlet {
private LogService logService = new LogServiceImpl();
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

int pageSize = 2;
String pageSizeStr = req.getParameter("pageSize"); //获取一页有几个
if(pageSizeStr!=null&&!pageSizeStr.equals("")){
pageSize = Integer.parseInt(pageSizeStr); //强转
}
int pageNumber = 1;
String pageNumberStr = req.getParameter("pageNumber"); //获取有几页
if(pageNumberStr!=null&&!pageNumberStr.equals("")){
pageNumber = Integer.parseInt(pageNumberStr); //强转
}

//最后跳转
req.setAttribute("pageinfo", logService.showPage(pageSize, pageNumber));
req.getRequestDispatcher("/log.jsp").forward(req, resp); //跳转

}
}

书写log.jsp页面

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
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<table border="1">
<tr>
<th>转账帐号</th>
<th>收款帐号</th>
<th>转账金额</th>
</tr>
<c:forEach items="${pageinfo.list}" var="log">
<tr>
<td>${log.accOut }</td>
<td>${log.accIn }</td>
<td>${log.money }</td>
</tr>
</c:forEach>
</table>
<a href="show?pageSize=${pageinfo.pageSize }&pageNumber=${pageinfo.pageNumber-1}" <c:if test="${pageinfo.pageNumber<=1 }"> onclick="javascript:return false;"</c:if>>上一页</a>
<a href="show?pageSize=${pageinfo.pageSize }&pageNumber=${pageinfo.pageNumber+1}" <c:if test="${pageinfo.pageNumber>=pageinfo.total }"> onclick="javascript:return false;"</c:if>>下一页</a>
</body>
</html>

全局配置文件添加mappers

1
2
3
4
<mappers>
<mapper resource="com/bjsxt/mapper/AccountMapper.xml"/> <!-- 直接调用配置文件 执行sql语句 -->
<mapper resource="com/bjsxt/mapper/LogMapper.xml"/> <!-- 直接调用配置文件 执行sql语句 -->
</mappers>

总结

最终代码结构:

最终结果:


×

纯属好玩

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

文章目录
  1. 1. 前期准备
    1. 1.1. 数据库准备
    2. 1.2. 导入jar包
    3. 1.3. 准备全局配置文件mybatis.xml文件
    4. 1.4. 准备pojo包的实体类Account
  2. 2. 准备mapper包下的AccountMapper.xml文件
  3. 3. 准备serive包下的AccountService接口
  4. 4. 准备1.0版本的serviceimpl包
  5. 5. 准备servlet包下的TransferServlet类
  6. 6. 准备登陆/失败/转账查询的页面
    1. 6.1. log显示成功界面
    2. 6.2. index主页面界面
    3. 6.3. error错误界面
  7. 7. 准备log4j (查错)
    1. 7.1. 带入jar包和配置文件log4j.properties
    2. 7.2. 全局配置文件中配置log4j
    3. 7.3. 执行结果
  8. 8. 日志记录
    1. 8.1. 创建表log
    2. 8.2. 新增log实体类
    3. 8.3. 新增关于log表的配置xml文件
    4. 8.4. 在serviceimpl实现类添加
    5. 8.5. 日志文件显示转账信息(log4j)
  9. 9. 分页展示功能
    1. 9.1. mapper包xml里面添加分页功能的sql语句
    2. 9.2. 添加分页显示的实体类
    3. 9.3. service层接口实现方法
    4. 9.4. service实现类
    5. 9.5. 准备servlet类
    6. 9.6. 书写log.jsp页面
    7. 9.7. 全局配置文件添加mappers
  10. 10. 总结
,