银行存款业务
首先,定义一个工具常量类. Constants.java
package cn.itcast.util;
//常量池
public class Constants {
/*
* 与数据库db相关的常量
*/
public static final String DB_ERROR_GETCONNECTIONERROR="获取连接异常";
public static final String DB_ERROR_CLOSTRESULTSETERROR="获取结果集异常";
public static final String DB_ERROR_CLOSESTATEMENTERROR="关闭statement对象异常";
public static final String DB_ERROR_CLOSECONNECTIONERROR="关闭连接异常";
public static final String DB_ERROR_STARTERROR="开始事务异常";
public static final String DB_ERROR_COMMITERROR="提交事务异常";
public static final String DB_ERROR_ROLLBACKERROR="获取结果集异常";
public static final String DB_ERROR_SETERROR="设置连接的自动提交方式异常";
/*与数据操作有关的异常*/
public static final String DAO_ERROR_QUERYBYID="通过账号查询余额失败";
public static final String DAO_ERROR_UPDATEBYID="通过账号更新余额失败";
public static final String DAO_ERROR_INSERTBYID="添加账号失败";
……
}
第0步、index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<body>
存款页面:<br/>
<form action="${pageContext.request.contextPath}/servlet/InAccountServlet" method="post">
<table>
<tr>
<td>账户:td>
<td><input type="text" name="accountid"/>td>
tr>
<tr>
<td>存入金额:td>
<td><input type="text" name="inbalance"/>td>
tr>
<tr>
<td><input type="submit" value="存入"/>td>
<td>td>
tr>
table>
form>
body>
html>
第一步、DBManager.java
package cn.itcast.db;
public class DBManager {
private static DBManager dbManager=new DBManager();
private BasicDataSource bds=null;
private DBManager(){
bds=new BasicDataSource();
bds.setUsername("root");
bds.setPassword("root");
bds.setUrl("jdbc:mysql://localhost:3306/test");
bds.setDriverClassName("com.mysql.jdbc.Driver");
bds.setInitialSize(4);
bds.setMaxActive(10);
bds.setMaxIdle(5);
bds.setMinIdle(3);
bds.setMaxWait(5000);
}
public static DBManager getDBManager(){
return dbManager;
}
public Connection getConnection(){
Connection conn=null;
try {
conn = bds.getConnection();
} catch (SQLException e) {
e.printStackTrace();
//检查型异常---->运行时异常
throw new DBException(Constants.DB_ERROR_GETCONNECTIONERROR,e);
}
return conn;
}
public void closeResource(Connection conn,Statement statement,ResultSet rs){
try {
if(rs!=null){
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
throw new DBException(Constants.DB_ERROR_CLOSTRESULTSETERROR,e);
}finally{
try {
if(statement!=null){
statement.close();
}
} catch (SQLException e) {
e.printStackTrace();
throw new DBException(Constants.DB_ERROR_CLOSESTATEMENTERROR,e);
}finally{
try {
if(conn!=null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
throw new DBException(Constants.DB_ERROR_CLOSECONNECTIONERROR,e);
}
}
}
}
//开始事务,重新设置事务的提交方式为非自动提交
public void beginTransaction(Connection conn) {
try {
if(conn!=null){
conn.setAutoCommit(false);
//int x=1/0;
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new DBException(Constants.DB_ERROR_SETERROR,e);
}
}
public void commitTransaction(Connection conn) {
try {
if(conn!=null){
conn.commit();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new RuntimeException(Constants.DB_ERROR_COMMITERROR,e);
}
}
//回滚事务
public void rollbackTransaction(Connection conn) {
try {
if(conn!=null){
conn.rollback();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new DBException(Constants.DB_ERROR_ROLLBACKERROR,e);
}
}
//重新设置事务的提交方式为自动提交
public void resetTransaction(Connection conn) {
try {
if(conn!=null){
conn.setAutoCommit(true);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
throw new DBException(Constants.DB_ERROR_SETERROR,e);
}
}
}
第二步、InAccountServlet.java
package cn.itcast.web;
public class InAccountServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)throws Exception {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
PrintWriter out = response.getWriter();
String path="";
try {
//1.获取表单信息
String accountid=request.getParameter("accountid");
String sinbalance=request.getParameter("inbalance");
double inbalance=0;
if(sinbalance!=null&&!("".equals(sinbalance.trim()))){
inbalance=Double.parseDouble(sinbalance.trim());
}
//2.封装数据到javabean
InAccount inAccount=new InAccount();
inAccount.setAccountid(accountid);
inAccount.setInbalance(inbalance);
//3.实例化业务层对象
InAccountService inAccountService=new InAccountService();
inAccountService.saveInAccount(inAccount);
path="/success.jsp";
}catch(NumberFormatException e){
//e.printStackTrace();
request.setAttribute("errorInfo", "您输入的金额有误!");
path="/error.jsp";
} catch (Exception e) {
e.printStackTrace();
request.setAttribute("errorInfo", e.getMessage());
path="/error.jsp";
}
request.getRequestDispatcher(path).forward(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
第三步、InAccount.java
package cn.itcast.bean;
public class InAccount {
private String accountid;
private double inbalance;
……
}
第四步、InAccountService.java
package cn.itcast.service;
public class InAccountService {
/*
* 业务层是项目中处理业务的:
* * 开发中应该在业务层处理事务
* * 开发中应该在业务层获取数据库的连接Connection,传递到dao层
* 本例中的业务是:
* * 存入金额到inaccount表中
* * 查询(account)该账号的余额
* * 更新(account)中该账号的余额
* 以上三步操作,要么全部成功,要么全部失败
*/
public void saveInAccount(InAccount inAccount) {
DBManager dbManager=null;
Connection conn=null;
DaoInAccount daoInAccount=null;
DaoAccount daoAccount=null;
Account account=null;
try {
// 1.获取连接
dbManager=DBManager.getDBManager();
conn=dbManager.getConnection();
//1.1设置连接的提交方式为非自动提交
//conn.setAutoCommit(false);
//优化
dbManager.beginTransaction(conn);//到DBManager工具类中书写
/*************************业务**************************************/
//2.存入金额到inaccount表中
daoInAccount=DaoFactory.getDaoInAccount();
daoInAccount.saveInAccount(conn,inAccount);
//3.查询(account)该账号的余额,通过账号id查询
daoAccount=DaoFactory.getDaoAccount();
account=new Account();
//int x=1/0;
account.setAccountid(inAccount.getAccountid());
account= daoAccount.find(conn,account);
//System.out.println(account.getBalance());
//计算余额
double balance=inAccount.getInbalance()+account.getBalance();
account.setBalance(balance);
//4.更新(account)中该账号的余额
daoAccount.updateAccount(conn,account);
/***********************************************************************/
//提交事务
//conn.commit();
dbManager.commitTransaction(conn);
} catch (Exception e) {
// 所有的底层的异常全部抛到这里,在这里捕获,实现回滚
e.printStackTrace();
//回滚事务
dbManager.rollbackTransaction(conn);
throw new ServiceException(e.getMessage(),e);
}finally{
if(dbManager!=null){
dbManager.resetTransaction(conn);//很重要,重置为自动提交
dbManager.closeResource(conn, null, null);
}
}
}
}
第五步、DaoFactory.java
第六步、interface DaoInAccount.java
第七步、DaoInAccountImpl.java
package cn.itcast.dao.impl;
//存款dao抽象层
public class DaoInAccountImpl extends BaseDao implements DaoInAccount{
//往inaccount表中插入一条数据(存款)
public void saveInAccount(Connection conn, InAccount inAccount) {
//1.组织sql语句
String sql="insert into inaccount(accountid,inbalance) values(?,?)";
//2.设置参数的值
Object[] param=new Object[]{inAccount.getAccountid(),inAccount.getInbalance()};
String errorMessage="存款信息插入失败!";
//3.调用父类的方法
//注意下面的方法有抛出异常,运行时异常可以持续抛出,这一层不捕获
super.update(conn,sql,param,errorMessage);
}
}
第八步、DaoAccount.java
package cn.itcast.dao;
//对账号表操作的数据访问抽象层
public interface DaoAccount {
/*
* 通过账号查询余额,最终封装到javabean
*/
Account find(Connection conn, Account account);
/*
* 通过账号更新账户的余额
*/
void updateAccount(Connection conn, Account account);
}
InAccount.java
package cn.itcast.bean;
public class InAccount {
private String accountid;
private double inbalance;
……
}
第九步、DaoAccountImpl.java
package cn.itcast.dao.impl;
public class DaoAccountImpl extends BaseDao implements DaoAccount {
public Account find(Connection conn, Account account) {
//0.设置错误信息
String errorMsg=Constants.DAO_ERROR_QUERYBYID;
//1.组织sql语句
String sql="select accountid,balance from account where accountid=?";
//2.设置参数
Object[] param=new Object[]{account.getAccountid()};
//3.调用父类方法
Class clazz=Account.class;
account = (Account)super.findObjectById(conn,sql,param,clazz,errorMsg);
return account;
}
public void updateAccount(Connection conn, Account account) {
//0.设置错误信息
String errorMsg=Constants.DAO_ERROR_UPDATEBYID;
//1.组织sql语句
String sql="update account set accountid=?,balance=?";
//2.设置参数
Object[] param=new Object[]{account.getAccountid(),account.getBalance()};
//3.调用父类方法
super.update(conn, sql, param, errorMsg);
}
public void saveAccount(Connection conn, Account account) {
String errorMsg=Constants.DAO_ERROR_INSERTBYID;
String sql="insert into account(accountid,balance) values(?,?)";
Object[] param=new Object[]{account.getAccountid(),account.getBalance()};
super.update(conn, sql, param, errorMsg);
}
}
第十步、BaseDao.java
package cn.itcast.dao;
public abstract class BaseDao {
/*
* 该方法完成对数据库的insert update delete操作
*/
public void update(Connection conn, String sql, Object[] param,
String errorMessage) {
try {
QueryRunner query=new QueryRunner();
query.update(conn, sql, param);
} catch (SQLException e) {
e.printStackTrace();//这一行要写在前面
throw new DaoException(errorMessage,e);
}
}
//通过id查询账户余额
public Object findObjectById(Connection conn, String sql, Object[] param,
Class clazz, String errorMsg) {
Object obj=null;
try {
QueryRunner query=new QueryRunner();
obj = query.query(conn, sql,new BeanHandler(clazz), param);
} catch (SQLException e) {
e.printStackTrace();//这一行要写在前面
throw new DaoException(errorMsg,e);
}
return obj;
}
}
开户
第十二步、account.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" contentType="text/html;charset=UTF-8"%>
<html>
<head>
<title>开户title>
head>
<body>
开户:<form action="${pageContext.request.contextPath}/servlet/AccountServlet" method="post">
账号ID:<input name="accountid" type="text"/><br/>
<input type="submit" value="保存"/>
form>
body>
html>
第十三步、
package cn.itcast.web;
import java.io.IOException;
public class AccountServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws Exception {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
//获取账号id
String accountid=request.getParameter("accountid");
AccountService accountService=new AccountService();
Account account=new Account();
account.setAccountid(accountid);
account.setBalance(0.00);
accountService.saveAccount(account);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
第十四步
package cn.itcast.service;
//管理账号的业务层
public class AccountService {
public void saveAccount(Account account) {
DBManager dbManager=null;
Connection conn=null;
DaoAccount daoAccount=null;
try {
dbManager=DBManager.getDBManager();
conn=dbManager.getConnection();
//待用daoAccount的方法
daoAccount=DaoFactory.getDaoAccount();
daoAccount.saveAccount(conn,account);
} catch (Exception e) {
e.printStackTrace();
}finally{
if(dbManager!=null){
dbManager.closeResource(conn, null, null);
}
}
}
}
第十五步DaoAccount.java
第十六步DaoAccountImpl.java
package cn.itcast.dao.impl;
public class DaoAccountImpl extends BaseDao implements DaoAccount {
……
public void saveAccount(Connection conn, Account account) {
String errorMsg="创建新账户失败";
String sql="insert into account(accountid,balance) values(?,?)";
Object[] param=new Object[]{account.getAccountid(),account.getBalance()};
super.update(conn, sql, param, errorMsg);
}
}
总结:
javaWEB开发环境的搭建:
* 新建一个web工程day20Unit
* 引入项目所需要的jar包
* 包的层次关系
* 开发jsp页面
* 常量类
* 开发servlet
* 接收jsp的数据封装到javabean
* 调用业务层
* 开发业务层
* 获取Connection
* 获取dao层的对象(通过工厂)
* 控制事务
* 关闭连接
* 开发dao层
* 继承BaseDao
* 实现dao的接口
* 执行对数据库的操作(insert update delete select)
* 提供工厂类,用于业务层获取dao抽象接口实现类的对象
* 异常处理
异常的处理
异常的分类:
第一步、
package cn.itcast.exception;
// dao层异常
public class DaoException extends RuntimeException{
// new DBException(“数据库连接异常!”);
public DaoException(String message){
super(message);
}
public DaoException(String message,Throwable cause){
super(message, cause);
}
}
第二步、
package cn.itcast.exception;
/*
* 处理数据库的异常
*/
public class DBException extends RuntimeException {
/*
* new DBException("数据库连接异常!");
*/
public DBException(String message){
super(message);
}
public DBException(String message,Throwable cause){
super(message, cause);
}
}
第三步、
package cn.itcast.exception;
//业务层异常
public class ServiceException extends RuntimeException {
public ServiceException(String message) {
super(message);
}
public ServiceException(String message,Throwable cause){
super(message, cause);
}
}
第四步、
package cn.itcast.test;
import cn.itcast.exception.DaoException;
public class Dao {
public void a(){
if(true){
throw new DaoException("插入数据失败!");
//在他的上层用e.getMessage则可以打印出"插入数据失败!"
}
}
}
第五步、
package cn.itcast.test;
import cn.itcast.exception.ServiceException;
public class Service {
public void c(){
Dao dao=new Dao();
//try {
dao.a();
//} catch (Exception e) {
// System.out.println("*****************");
// e.printStackTrace();
// throw new ServiceException("保存数据失败!");
// }
}
}
第六步、
package cn.itcast.test;
public class Test {
public static void main(String[] args) {
Service service=new Service();
try {
service.c();
} catch (Exception e) {
System.out.println("yyyyyyyy"+e.getMessage());
}
}
}
运行Test.java则可以看到运行结果:
yyyyyyyy插入数据失败!
日志log4j
第一步、导包 log4j.jar
第二步、
第三步、
如何使用日志文件:
引入jar包 log4j-1.2.11.jar
在类(src)路径下增加log4j.properties文件(文件名不能改)
在java类中使用