-一、需求分析
-二、概要设计
-三、详细设计
1.添加车辆
2.实现租车业务
3.实现还车业务
数据层代码
-一、需求分析与数据表设计
需求图:
发现类:
01.moto类(汽车父类):
01.1:bus类(客车类)
01.2:car类(轿车类)
01.3:truck类(卡车类)
02.mototype类(汽车类型类)
03.用户类:软件系统的使用者,登录该系统 管理的 人,比如:管理员、业务经理等。
04.客户类:租车的人。
05.公司类:用于处理租车换车业务流程的人。
-二、概要设计
数据库设计:
-三、详细设计
实现各车的信息录入
一个问题:卡车跟大巴和轿车录入是不一样的,所以在业务层需要判断是什么车型,但这样代码比较臃肿,不利于扩展,不是面向对象编程。
解决:采用面向对象的特点(继承和多态),在moto类建立录入车信息的方法,这样轿车客车大巴继承moto类就可以有自己的录入车信息的方法。
代码演示:
moto类:
public abstract class Moto {private String mno; //车牌号
private int seatCount;
private MotoType mtype;
//这里省略get\set方法
public Moto(MotoType mtype,String mno,int seatCount){
this.mno = mno;
this.seatCount = seatCount;
this.mtype = mtype;
}
/**
* 把当前对象存储到数据库中
* @throws Exception
*/
public void saveDB() throws Exception{
CompanyDao dao = new CompanyDao();
try {
dao.addMoto(this);
} catch (Exception e) {
e.printStackTrace();
}finally{
dao.closeConnection();
}
}
}
car类:可以直接使用moto类中的方法
public class Car extends Moto{public Car(MotoType mtype,String mno) {super(mtype,mno, 5);}}
truck类:重写了moto类的saveDB()方法
public class Truck extends Moto{private int dun;private double priceEachDun; //每吨每天的单价public int getDun() {return dun;}public double getPriceEachDun() {return priceEachDun;}public void setPriceEachDun(double priceEachDun) {this.priceEachDun = priceEachDun;}public Truck(MotoType mtype, String mno, int seatCount,int dun) {super(mtype, mno, seatCount);this.dun = dun;}public double getDayMoney() {return priceEachDun*dun;}/** * 把当前对象存储到数据库中 ----------重写 * @throws Exception */@Overridepublic void saveDB() throws Exception{CompanyDao dao = new CompanyDao();try {dao.beginTransaction();dao.addMoto(this);TruckEntity truckEntity = new TruckEntity();truckEntity.setMno(this.getMno());truckEntity.setDun(dun);truckEntity.setPriceEachDun(priceEachDun);dao.addTruck(truckEntity);dao.commit();} catch (Exception e) {e.printStackTrace();dao.rollback();throw e;}finally{dao.closeConnection();}}}
在业务逻辑层方法就很简单了:
private List<Moto> motos;/*** 添加汽车* @param moto* @throws Exception*/public void addMoto(Moto moto) throws Exception{if(moto != null ){moto.saveDB(); //OO多态motos.add(moto);}else{throw new Exception("入参moto错误");}}
2.实现租车业务
图解:
注意:由于整个租车过程包含多个表的修改,比如加入两个订单在差不多时间操作同一辆车,肯定会有一个订单有问题,这是就需要保证事务的一致性和完整性。
在业务逻辑层的代码就可以:
public class RentCompany {private String name;private List<Moto> motos; //待租赁的汽车public String getName() {return name;}public List<Moto> getMotos() {return motos;}public RentCompany(String name){this.name = name;motos = new ArrayList<Moto>(50);}/** * 汽车租赁 * @param motos * @param client * @param rentinfo * @return 租赁成功,返回订单号 * @throws Exception */public String rent(List<Moto> motos,TClient client,TRentInfo rentinfo) throws Exception{String rentno = null;if(motos != null && client != null && rentinfo!= null){CompanyDao dao = new CompanyDao();try {dao.beginTransaction(); //开启事务//添加客户数据dao.addTClient(client);//添加汽车租赁信息rentno = dao.addRentInfo(rentinfo);//添加租赁明细for(Moto moto : motos){TRentDetail rentDetail = getTRentDetail(rentno,moto); dao.addRentDetail(rentDetail);}dao.commit(); //提交事务} catch (Exception e) {dao.rollback(); //回滚事务rentno = null;throw e;}finally{dao.closeConnection();}}else{throw new Exception("入参错误,请检查");}return rentno;}private TRentDetail getTRentDetail(String rentno,Moto moto){TRentDetail detail = new TRentDetail();detail.setMno(moto.getMno());detail.setRentno(rentno);detail.setDaymoney(moto.getDayMoney());return detail;}}
3.实现还车业务
业务流程:计算租金总额、添加还车信息、给订单写入租金总额、设置车辆信息
/*** 还车,计算租赁的总价* @param moto* @return*/public double rentBack(String rentno) throws Exception{double allMoney = 0;if(rentno != null){CompanyDao dao = new CompanyDao();try { dao.beginTransaction();//计算租金总额allMoney = dao.countAllPayMoney(rentno);//添加还车信息dao.addRentBackInfo(rentno);//给订单写入租金总额dao.writeAllPayMoney(rentno, allMoney);//设置车辆的状态dao.setRentBackMotoState(rentno);dao.commit();} catch (Exception e) {dao.rollback();throw e;}finally{dao.closeConnection();}}else{throw new Exception("入参错误");}return allMoney;}
对应dao层代码:
basedao
public class BaseDao {protected Connection conn;public Connection getConn() {return conn;}public void setConn(Connection conn) {this.conn = conn;}public void openConnection() throws ClassNotFoundException,SQLException{ //通过反射技术,对oracel的驱动对象进行类的加载 (其实是在做类型检查)//在类的加载时,会调用OracleDriver中的静态代码块和静态变量初始化if(this.conn == null || this.conn.isClosed()){Class.forName("oracle.jdbc.driver.OracleDriver"); conn = DriverManager.getConnection("jdbc:oracle:thin:@10.0.19.252:1521:orcl","testdb","1111");}}public void beginTransaction() throws Exception{this.openConnection();if(this.conn != null){this.conn.setAutoCommit(false); //手动提交模式}}public void commit() throws Exception{if(this.conn != null){this.conn.commit();}}public void rollback() throws Exception{if(this.conn != null){this.conn.rollback();}}public void closeConnection() {if(this.conn != null){try {this.conn.close();} catch (Exception e) {e.printStackTrace();}}}}
public class CompanyDao extends BaseDao{/** * 根据订单号,计算需要的租金总额 * @param rentno * @return * @throws Exception */public double countAllPayMoney(String rentno) throws Exception{double allMoney = 0;double dayMoneys = 0;String sql = " select sum(daymoney) dayMoneys from trentinfo r,trentdetail d where r.rentno = d.rentno" + " and r.rentno=?";this.openConnection();PreparedStatement ps = this.conn.prepareStatement(sql);ps.setString(1,rentno);ResultSet rs = ps.executeQuery();while(rs.next()){dayMoneys = rs.getDouble("dayMoneys");}RentinfoDto rentinfo = getRentInfo(rentno);int days = (int)((new Date()).getTime() - rentinfo.getRentBeginDate().getTime())/(24*3600*1000) + 1; allMoney = dayMoneys*days;return allMoney;}/** * 根据订单编号,返回订单信息 * @param rentno * @return */public RentinfoDto getRentInfo(String rentno) throws Exception{RentinfoDto rentinfo = null;String sql = " select r.rentno,r.clno,r.eno,r.operator,r.rentbengindate,r.diyamoney,r.payallmoney, b.backdate " +" from trentinfo r left join trentback b on r.rentno = b.rentno and r.rentno=?";this.openConnection();PreparedStatement ps = this.conn.prepareStatement(sql);ps.setString(1,rentno);ResultSet rs = ps.executeQuery();while(rs.next()){rentinfo = new RentinfoDto();rentinfo.setBackDate(rs.getDate("backdate"));rentinfo.setClno(rs.getString("clno"));rentinfo.setDiyaMoney(rs.getDouble("diyamoney"));rentinfo.setEno(rs.getString("eno"));rentinfo.setOperator(rs.getString("operator"));rentinfo.setPayAllMoney(rs.getDouble("payallmoney"));rentinfo.setRentBeginDate(rs.getDate("rentbengindate"));rentinfo.setRentno(rs.getString("rentno"));}return rentinfo;}/** * 还车时,给订单写入租金总额 * @param rentno * @param allMoney * @throws Exception */public void writeAllPayMoney(String rentno,double allMoney) throws Exception{String sql = "update trentinfo set payallmoney=? where rentno=?";this.openConnection();PreparedStatement ps = this.conn.prepareStatement(sql);ps.setDouble(1, allMoney);ps.setString(2, rentno);ps.executeUpdate();ps.close();}/** * 添加还车信息 * @param rentno * @throws Exception */public void addRentBackInfo(String rentno) throws Exception{String sql = "insert into trentback values(?,?)";this.openConnection();PreparedStatement ps = this.conn.prepareStatement(sql);ps.setString(1, rentno);ps.setTimestamp(2,new java.sql.Timestamp(new Date().getTime()));ps.executeUpdate();ps.close();}/** * 还车时,设置所有订单中的车辆状态为'01' * @param rentno * @throws Exception */public void setRentBackMotoState(String rentno) throws Exception{String sql = "select d.mno from trentinfo r,trentdetail d where r.rentno = d.rentno and r.rentno=?";this.openConnection();PreparedStatement ps = this.conn.prepareStatement(sql);ps.setString(1,rentno);ResultSet rs = ps.executeQuery();while(rs.next()){String mno = rs.getString("mno");updateRentBackMotoState(mno);}rs.close();ps.close(); }public void updateRentBackMotoState(String mno) throws Exception{String sql = "update tmoto set state='01' where mno=?";this.openConnection();PreparedStatement ps = this.conn.prepareStatement(sql);ps.setString(1, mno);ps.executeUpdate(); ps.close();}/** * 添加客户数据 * @param client * @throws Exception */public void addTClient(TClient client) throws Exception{//查询客户是否存在boolean bRet = isHaveClient(client.getTel());if(!bRet){//添加客户数据String sql = "insert into tclient values(?,?,?,?,?)";this.openConnection();PreparedStatement ps = this.conn.prepareStatement(sql);ps.setString(1, client.getTel());ps.setString(2, client.getCname());ps.setString(3, client.getCid());ps.setString(4, client.getTel());ps.setString(5, client.getAddress());ps.executeUpdate();ps.close();}}/** * 通过手机号,查询指定用户是否存在 * @param tel * @return */private boolean isHaveClient(String tel) throws Exception{boolean bRet = false;String sql = "select * from tclient where tel=?";this.openConnection();PreparedStatement ps = this.conn.prepareStatement(sql);ps.setString(1, tel);ResultSet rs = ps.executeQuery();while(rs.next()){bRet = true;}rs.close();ps.close();return bRet;}/** * 汽车租赁 * @param rentinfo * @return 返回订单号 * @throws Exception */public String addRentInfo(TRentInfo rentinfo) throws Exception{String sql = "insert into trentinfo values(?,?,?,?,?,?,?)";this.openConnection();PreparedStatement ps = this.conn.prepareStatement(sql);SimpleDateFormat sd = new SimpleDateFormat("yyyyMMdd");String rentno = "rno-" + sd.format(new Date()) + "-" + (new Date()).getTime();ps.setString(1, rentno);ps.setString(2, rentinfo.getClno());ps.setString(3, rentinfo.getEno());ps.setString(4, rentinfo.getOperator()); ps.setDate(5, new java.sql.Date(rentinfo.getRentBeginDate().getTime()));ps.setDouble(6, rentinfo.getDiyaMoney());ps.setDouble(7, rentinfo.getPayAllMoney());ps.executeUpdate();ps.close();return rentno;}/** * 添加租赁明细 * @param rentDetail * @throws Exception */public void addRentDetail(TRentDetail rentDetail) throws Exception{//添加明细String sql = "insert into TRentDetail values(seq_rentdetail_id.nextval,?,?,?)";this.openConnection();PreparedStatement ps = this.conn.prepareStatement(sql);ps.setString(1, rentDetail.getRentno());ps.setString(2, rentDetail.getMno());ps.setDouble(3,rentDetail.getDaymoney());ps.executeUpdate();ps.close();//修改汽车状态值updateMotoStateByRent(rentDetail.getMno());}/** * 修改汽车状态值,从未出租改为出租中 * @param moto * @throws Exception */private void updateMotoStateByRent(String mno) throws Exception{ String sql = "update tmoto set state='02' where mno=? and state='01'"; this.openConnection(); PreparedStatement ps = this.conn.prepareStatement(sql); ps.setString(1, mno); int iRet = ps.executeUpdate(); if(iRet==0){ throw new MotoRentFailException( mno+ ",该车已被别人租用,请重新选择"); } ps.close();}/** * 添加汽车单表数据 * @param moto * @throws Exception */public void addMoto(Moto moto) throws Exception{String sql = "insert into tmoto values(?,?,?,?)";this.openConnection();PreparedStatement ps = this.conn.prepareStatement(sql);ps.setString(1,moto.getMno());ps.setString(2,moto.getMtype().getTno());ps.setInt(3, moto.getSeatCount());ps.setString(4, MotoState.PREPARED_RENT);ps.executeUpdate();ps.close();}/** * 添加卡车单表数据 * @param truck * @throws Exception */public void addTruck(TruckEntity truck) throws Exception{String sql = "insert into truck values(?,?,?)";this.openConnection();PreparedStatement ps = this.conn.prepareStatement(sql);ps.setString(1, truck.getMno());ps.setInt(2, truck.getDun());ps.setDouble(3, truck.getPriceEachDun());ps.executeUpdate();ps.close();}}
本文出自 “秦斌的博客” 博客,请务必保留此出处http://qinbin.blog.51cto.com/11773640/1967828