mybatis项目1.0 11.26

 一、账户转账小项目

1.项目结构:

2.简单介绍一下包:

  • dao  持久化层(专门负责数据表的CRUD,没有任何业务上的操作)
  • impl 接口实现
  • exception 异常类
  • pojo 对象
  • service 业务逻辑层
  • util 工具
  • web 表示层(页面)

 3.介绍相关类(从前端往后端走)

1.transfer.html 转账界面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>转账界面</title>
</head>
<body>
<form action="/mybatis_project_war_exploded/transfer" method="post">
    转出账号:<input type="text" name="fromActno"><br>
    转入账号:<input type="text" name="toActno"><br>
    转账金额:<input type="text" name="money"><br>
    <input type="submit" value="转账">
</form>
</body>
</html>

 2.web.xml   进行界面跳转文件配置

<?xml version="1.0" encoding="UTF-8"?>

        <web-app metadata-complete="true"
                 version="4.0"
                 xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xmlns="http://xmlns.jcp.org/xml/ns/javaee">
        <welcome-file-list>
                <welcome-file>transfer.html</welcome-file>
        </welcome-file-list>

        <servlet>
                <servlet-name>transfer</servlet-name>
                <servlet-class>com.jiang.web.AccountServlet</servlet-class>
        </servlet>
        <servlet-mapping>
                <servlet-name>transfer</servlet-name>
                <url-pattern>/transfer</url-pattern>
        </servlet-mapping>
</web-a

3.AccountServlet类   接收数据并进行处理 (调用service层)

  1.  servlet不处理业务,只调用相关层
  2. 层与层之间要用接口去连接---面向接口编程
package com.jiang.web;

import com.jiang.exceptions.MoneyNotEnoughException;
import com.jiang.exceptions.TransferException;
import com.jiang.service.AccountService;
import com.jiang.service.impl.AccountServiceImpl;
import org.apache.ibatis.javassist.CannotCompileException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class AccountServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String fromActno = req.getParameter("fromActno");
        String toActno = req.getParameter("toActno");
        String m = req.getParameter("money");
        double money = Double.parseDouble(m);
         //1.servlet不处理业务的,
        // 2.此处调用service的转账方法进行转账
        //3.表示层调业务逻辑层
        //4.层与层之间要用接口去连接(面向接口编程)
        AccountService accountService=new AccountServiceImpl();

        try {
            accountService.transfer(fromActno,toActno,money);
            //5.调用视图层,成功就跳转成功界面
            resp.sendRedirect(req.getContextPath()+"/success.html");
        } catch (MoneyNotEnoughException e) {
            resp.sendRedirect(req.getContextPath()+"/moneynotenough.html");
        } catch (TransferException e) {
            resp.sendRedirect(req.getContextPath()+"/transfererror.html");
        } catch (NullPointerException e) {
            resp.sendRedirect(req.getContextPath() + "/transfererror.html");
        } catch (CannotCompileException e) {
            e.printStackTrace();
        }
    }
}

4. AccountService接口(实现层与层连接)

  1.  接口方法不需要public修饰(多余的)
package com.jiang.service;

import com.jiang.exceptions.MoneyNotEnoughException;
import com.jiang.exceptions.TransferException;
import org.apache.ibatis.javassist.CannotCompileException;

//账户业务类
public interface AccountService {
    //1.修饰符“public”对于接口方法是多余的
    public void transfer(String fromActno,String toActno,double money) throws MoneyNotEnoughException, TransferException, CannotCompileException;
}

 5.AccountServiceImpl   实现类(存在部分后面学习的内容先不讲---即mybatis自动生成dao的方法)

package com.jiang.service.impl;
import com.jiang.dao.AccountDao;
import com.jiang.dao.impl.AccountDaoImpl;
import com.jiang.exceptions.MoneyNotEnoughException;
import com.jiang.exceptions.TransferException;
import com.jiang.pojo.Account;
import com.jiang.service.AccountService;
import com.jiang.utils.GenerateDaoProxy;
import com.jiang.utils.MybatisTool;
import org.apache.ibatis.javassist.CannotCompileException;
import org.apache.ibatis.session.SqlSession;

public class AccountServiceImpl implements AccountService {


    @Override
    //这部分是前端接受的数据(表示层传来的数据给业务逻辑层)
    public void transfer(String fromActno, String toActno, double money) throws MoneyNotEnoughException, TransferException, CannotCompileException {
        //我们自己的
        //AccountDao accountDao = (AccountDao) GenerateDaoProxy.generate(MybatisTool.getsqlsession(), AccountDao.class);

        //mybatis实现的代理机制
        //AccountDao accountDao = MybatisTool.getsqlsession().getMapper(AccountDao.class);
        //事务控制部分:
        SqlSession sqlSession=MybatisTool.getsqlsession();
        //1.判断转出账户余额是否充足(select)
        AccountDaoImpl accountDao = new AccountDaoImpl();
        //测试GenerateDaoProxy
        //Object o = GenerateDaoProxy.generate(sql, AccountDao.class);
        Account fromaccount = accountDao.selectByActno(fromActno);
        Account toaccount = accountDao.selectByActno(toActno);
        Double fromActnoMoney = fromaccount.getbalance();
        Double toaccountMoney = toaccount.getbalance();
        //2.如果充足,则转账成功,
        //3.不充足,则转账失败
        if (fromActnoMoney<money) {
            //不充足
            //子类不能抛比父类更宽泛的异常,
            //这里会自动给父接口抛异常
            //不能try,catch 自己创造异常自己抓?
            throw new MoneyNotEnoughException("钱不够!");
        }else {
            //充足
            fromaccount.setbalance(fromActnoMoney-money);
            toaccount.setbalance(toaccountMoney+money);
            int count = accountDao.updateActno(fromaccount);
            //模拟中间异常,查看是否会少钱
            //String string=null;
            //string.toString();
            //结果:少钱 ---  事务控制没有控制好。
            count += accountDao.updateActno(toaccount);
            if (count!=2) {
                throw new TransferException("转账失败");
            }

            //事务的提交与关闭  首先是不好使得,因为事务不一致
            //解决方法: ThreadLocal绑定一个sqlsession
            sqlSession.commit();
            //sql.close(); 此处就调用工具类的关闭
            MybatisTool.close(sqlSession);
        }
    }
}

其中调用了工具类、持久层(数据库操作)、相关异常类,下面来介绍一下

6.mybatis 工具类(获取sqlsession,后期会有优化涉及到事务管理)

package Tool;

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 MybatisTool {
    private MybatisTool() {

    }
    public static SqlSessionFactory sqlSessionFactory;

    static {
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        try {
            sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatisconfig.xml"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static SqlSession getsqlsession() {
        return sqlSessionFactory.openSession();
    }

}

 7.dao层(CRUD)

package com.jiang.dao;

import com.jiang.pojo.Account;


public interface AccountDao {

     Account selectByActno(String actno);
     int updateActno(Account account);

}

 其实现类:

package com.jiang.dao.impl;

import com.jiang.dao.AccountDao;
import com.jiang.pojo.Account;
import com.jiang.utils.MybatisTool;
import org.apache.ibatis.session.SqlSession;

public class AccountDaoImpl implements AccountDao {
    @Override
    public Account selectByActno(String actno) {
        SqlSession sqlSession = MybatisTool.getsqlsession();
        Object o = sqlSession.selectOne("account.selectone", actno);
            Account account=(Account) o;
            return account;
    }

    @Override
    public int updateActno(Account account) {
        SqlSession sqlSession = MybatisTool.getsqlsession();

        int count = sqlSession.update("account.updateone", account);
 
        return count;
    }
}

8. MoneyNotEnoughException和 TransferException    异常类

package com.jiang.exceptions;

public class MoneyNotEnoughException extends Exception{
    public MoneyNotEnoughException(){}
    public MoneyNotEnoughException(String msg){
        super(msg);
    }
}

package com.jiang.exceptions;

public class TransferException extends Exception{
    public TransferException(){}
    public TransferException(String msg){super(msg);}
}

自己不清楚的知识点:

  1.  double money = Double.parseDouble(m);   转化为double类型

但是以上会出现一个问题

(AccountServiceImpl)当两者进行更新时,中间出现异常的话,会少钱,者就涉及到了一个事务控制管理

 int count = accountDao.updateActno(fromaccount);
            //模拟中间异常,查看是否会少钱
            String string=null;
            string.toString();
            //结果:少钱 ---  事务控制没有控制好。
            count += accountDao.updateActno(toaccount);

两者的事务不一致,所以会出现问题:

怎样解决??? ---   ThreadLocal

9.MybatisTool更新

 将一个sqlsession存入ThreaLocal中,从中取。

package com.jiang.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 MybatisTool {
    private MybatisTool() {

    }
    public static SqlSessionFactory sqlSessionFactory;

    static {
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        try {
            sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("Config.xml"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //全局的服务器级别的 一个服务器当中只能定义一个
    //第二点:只要调用了openSqlSession方法就会创建一个新的sqlsession对象   不安全
    //怎样安全,就是放在local里面,每个地方都可以用
    //生命周期:
    //sqlsessionbuilder  为sqlsession而生  创完就无
    //sqlsessionfactory  一直运行  不用重复创建多次
    //sqlsession  一个线程一个sqlsession
    private static ThreadLocal<SqlSession> local=new ThreadLocal<>();

    public static SqlSession getsqlsession() {
        SqlSession sqlSession = local.get();
        if (sqlSession==null) {
             sqlSession = sqlSessionFactory.openSession();
            //第一次,得将其绑定到该线程上
            local.set(sqlSession);
        }
        return  sqlSession;
    }


    //关闭sqlsession对象,并从当前线程移除sqlsession
    public  static void close(SqlSession sqlSession){
        if (sqlSession!=null) {
            sqlSession.close();
            local.remove();
            //因为tomcat是支持线程池的,如果当先t1线程没有移除的话,下次还会使用该线程
        }
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值