-一、需求分析
-二、概要设计
-三、详细设计
1.添加车辆
2.实现租车业务
3.实现还车业务
数据层代码
-一、需求分析与数据表设计
需求图:
发现类:
01.moto类(汽车父类):
01.1:bus类(客车类)
01.2:car类(轿车类)
01.3:truck类(卡车类)
02.mototype类(汽车类型类)
03.用户类:软件系统的使用者,登录该系统 管理的 人,比如:管理员、业务经理等。
04.客户类:租车的人。
05.公司类:用于处理租车换车业务流程的人。
-二、概要设计
数据库设计:
-三、详细设计
-
实现各车的信息录入
一个问题:卡车跟大巴和轿车录入是不一样的,所以在业务层需要判断是什么车型,但这样代码比较臃肿,不利于扩展,不是面向对象编程。
解决:采用面向对象的特点(继承和多态),在moto类建立录入车信息的方法,这样轿车客车大巴继承moto类就可以有自己的录入车信息的方法。
代码演示:
moto类:
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
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类中的方法
1
2
3
4
5
|
public
class
Car
extends
Moto{
public
Car(MotoType mtype,String mno) {
super
(mtype,mno,
5
);
}
}
|
truck类:重写了moto类的saveDB()方法
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
41
42
43
44
45
46
|
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
*/
@Override
public
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();
}
}
}
|
在业务逻辑层方法就很简单了:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
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.实现租车业务
图解:
注意:由于整个租车过程包含多个表的修改,比如加入两个订单在差不多时间操作同一辆车,肯定会有一个订单有问题,这是就需要保证事务的一致性和完整性。
在业务逻辑层的代码就可以:
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
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.实现还车业务
业务流程:计算租金总额、添加还车信息、给订单写入租金总额、设置车辆信息
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
|
/**
* 还车,计算租赁的总价
* @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
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
41
42
43
44
45
46
47
48
49
50
|
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();
}
}
}
}
|
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
|
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();
}
}
|
版权声明:原创作品,如需转载,请注明出处。否则将追究法律责任
本文转自 叫我北北 51CTO博客,原文链接:http://blog.51cto.com/qinbin/1967828