文章目录
壹. 三层架构的介绍
1. 什么是三层
- 表示层
- 命名: XXXView
- 职责:手机用户的数据和需求、展示数据。
- 业务逻辑层
- 命名: XXXServiceImpl
- 职责:数据加工处理,调用DAO完成业务实现、控制事务
- 数据访问层
- 命名:XXXDaoImpl
- 职责:向业务层提供数据,将业务层加工后的数据同步到数据库
2. 三层架构核心流程
3. 三层架构项目搭建(按开发步骤)
- utils 存放工具类(DBUtils)
- entity 存放实体类(Person)
- dao 存放DAO接口(PersonDao)
- impl 存放DAO接口实现类(PersonDaoImpl)易于更新换代]
- service 存放service接口(PersonService)
- impl 存放service接口实现类(PersomServiceImpl)
- view 存放程序启动类(main)
程序设计时,考虑已修改,易扩展,为Service层和DAO层设计接口,便于未来更换实现类
贰. 代码
1. 先放出本项目用到的数据库
CREATE TABLE ACCOUNT(
cardNo VARCHAR(20) PRIMARY KEY,
PASSWORD VARCHAR(20) NOT NULL,
NAME VARCHAR(20) NOT NULL,
balance DOUBLE NOT NULL
)CHARSET=utf8;
SELECT * FROM ACCOUNT ;
INSERT INTO ACCOUNT VALUES('6002','1234','Joe',10000);
INSERT INTO ACCOUNT VALUES('6003','1234','Gavin',1000);
2. Account类(entity类)
package com.account;
public class Account {
private String cardNo;
private String password;
private String name;
private double balance;
public Account() {
}
public Account(String cardNo, String password, String name, double balance) {
this.cardNo = cardNo;
this.password = password;
this.name = name;
this.balance = balance;
}
public String getCardNo() {
return cardNo;
}
public void setCardNo(String cardNo) {
this.cardNo = cardNo;
}
public String getPassword() {
return password;
}
public void setPassword(String 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;
}
@Override
public String toString() {
return "Account{" +
"cardNo='" + cardNo + '\'' +
", password='" + password + '\'' +
", name='" + name + '\'' +
", balance=" + balance +
'}';
}
}
3. DBUtils工具类
package com.account;
import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
public class DButils {
private static final Properties prop=new Properties();
private static ThreadLocal<Connection> threadLocal=new ThreadLocal<>();
static{
InputStream is = DButils.class.getResourceAsStream("/Utils.properties");
try {
prop.load(is);
Class.forName(prop.getProperty("Driver"));
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
//获取连接
public static Connection getConnection(){
Connection connection =threadLocal.get();//将当前线程中绑定的Connection对象,赋值给connection
try {
if(connection==null){
connection = DriverManager.getConnection(prop.getProperty("url"), prop.getProperty("username"), prop.getProperty("password"));
threadLocal.set(connection);//把链接存在当前线程共享中
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return connection;
}
//开启事务
public static void begin(){
Connection connection=getConnection();
try {
connection.setAutoCommit(false);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
//提交事务
public static void commit(){
Connection connection=null;
try {
connection=getConnection();
connection.commit();
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
CloseAll(connection,null,null);
}
}
//回滚事务
public static void rollback(){
Connection connection=null;
try {
connection= getConnection();
connection.rollback();
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
CloseAll(connection,null,null);
}
}
//关闭所有
public static void CloseAll(Connection connection, Statement statement, ResultSet resultSet){
try{
if(resultSet!=null) resultSet.close();
if(statement!=null) statement.close();
if(connection!=null) {
connection.close();
threadLocal.remove();//关闭连接后,移除已关闭connection对象
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
4. AccountDao接口
package com.account;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public interface AccountDao {
int insert(Account account);
int delete(Account account);
int update(Account account);
Account select(String cardNo);
}
5. AccountDao的实现类AccountDaoImpl
package com.account;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class AccountDaoImpl implements AccountDao{
public int insert(Account account) {return 0;}
public int delete(Account account) {return 0;}
public int update(Account account) {
Connection connection=null;
PreparedStatement preparedStatement=null;
String sql="update account set password =?,name=?,balance=? where cardNo=?";
connection=DButils.getConnection();
try {
preparedStatement=connection.prepareStatement(sql);
preparedStatement.setString(1,account.getPassword());
preparedStatement.setString(2,account.getName());
preparedStatement.setDouble(3,account.getBalance());
preparedStatement.setString(4,account.getCardNo());
int result = preparedStatement.executeUpdate();
return result;
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
DButils.CloseAll(null,preparedStatement,null);
}
return 0;
}
public Account select(String cardNo){
Connection connection=null;
PreparedStatement preparedStatement=null;
ResultSet resultSet=null;
Account account=null;
String sql="select * from account where cardNo=?";
connection=DButils.getConnection();
try {
preparedStatement=connection.prepareStatement(sql);
preparedStatement.setString(1,cardNo);
resultSet=preparedStatement.executeQuery();
if(resultSet.next())
{
return account=new Account(resultSet.getString("cardNo"),resultSet.getString("password"),
resultSet.getString("name"),resultSet.getDouble("balance"));
}
} catch (SQLException throwables) {
throwables.printStackTrace();
} finally {
DButils.CloseAll(null,preparedStatement,resultSet);
}
return null;
}
}
6. AccountService接口
package com.account;
public interface AccountService {
void transfer(String fromNo,String password,String toNo,double money);
}
7. AccountService的实现类AccountServiceImpl
package com.account;
import java.sql.Connection;
import java.sql.SQLException;
public class AccountServiceImpl implements AccountService{
public void transfer(String fromNo,String password,String toNo,double money){
AccountDaoImpl accountDao = new AccountDaoImpl();
try {
//调用DBUtils开启事务
DButils.begin();
//1.验证fromNo是否存在
Account account = accountDao.select(fromNo);
if(account==null) throw new RuntimeException("卡号不存在");
//2.验证密码是否正确
if(! account.getPassword().equals(password)) throw new RuntimeException("卡号或者密码错误");
//3.验证余额是否足够
if(account.getBalance()<money) throw new RuntimeException("余额不足");
//4.验证toNo是否存在
Account toAccount = accountDao.select(toNo);
if(toAccount==null) throw new RuntimeException("对方卡号不存在");
//5.减少fromNo的余额
account.setBalance(account.getBalance()-money);
accountDao.update(account);
// int i=10/0;//生成异常的代码
//6.增加toNo的余额
toAccount.setBalance(toAccount.getBalance()+money);
accountDao.update(toAccount);
System.out.println("转账成功");
//转账成功,提交事务
DButils.commit();
} catch (RuntimeException e) {
System.out.println("转账失败");
//如果当前程序出现异常,则回滚当前整个事务
DButils.rollback();
e.printStackTrace();
}
}
}
8. 测试类TestAccount
package com.account;
public class TestAccount {
public static void main(String[] args) {
AccountServiceImpl accountService = new AccountServiceImpl();
accountService.transfer("6002","1234","6003",1000);
}
}