数据库实验八数据库编程Word格式.docx
《数据库实验八数据库编程Word格式.docx》由会员分享,可在线阅读,更多相关《数据库实验八数据库编程Word格式.docx(12页珍藏版)》请在冰豆网上搜索。
对于应用程序的外观设计和其他框架组件(如Struts、Spring、Swing等)不做限制;
有明显抄袭痕迹、雷同者本次成绩作废。
三.实验内容
内容提纲:
1)整体实现思想、方案等描述;
2)模块(或子系统)设计与实现(各个模块要分开按序填写!
)
(主要包括运行界面截图、对应存储过程脚本、调用代码、界面逻辑处理代码等体现个人工作的内容。
说明:
截图精简、注释适当,尽量去除无关代码;
对应用程序设计方案的图形化表示不做要求,如果绘图请采用一致的方法。
四.实验过程及结果
1)系统实现思想及方案
本系统采用JDBC链接数据库,通过JDBC调用数据库中已经实现的存储过程,实现增,删,改,查及其他操作。
系统分为六个模块,分别调用相应的存储过程实现相应的功能。
主要实现方案如下:
用户通过JSP和与系统交互,Servlet得到用户的请求,调用Service中的方法,Dao层根据service层的需求来调用相应的存储过程,并把存储过程中数据中执行的结果存储到集合中在逐层传递给用户。
其中,DAO层中使用c3p0连接池来统一管理连接,这样做的好处是不用每次操作数据库都需要创建连接,而是使用连接池提供的连接,使用之后再重新归还给连接池,这样达到了连接复用的效果,提升了软件的性能。
2)模块设计与实现
系统主界面:
子模块1:
调用存储过程增加单条记录
运行截图:
存储过程脚本:
createprocedureInsertOneRecord
@IDint,
@FirstNamevarchar(20),
@LastNamevarchar(20),
@Phonevarchar(11),
@Emailvarchar(20)
as
insertintoCustomer
values(
@id,
@FirstName,
@LastName,
@Phone,
@Email)
go
调用代码:
publicstaticvoidexecuteAdd(Customerc)throwsSQLException{
QueryRunnerqr=newTxQueryRunner();
Stringsql="
{callInsertOneRecord(?
?
)}"
;
Object[]params={c.getID(),c.getFirstName(),c.getLastName(),c.getPhone(),c.getEmail()}
qr.update(sql,params);
}
子模块2:
调用存储过程修改单条记录
createprocedureUpdateOneRecord
updateCustomer
set
FirstName=@FirstName,
LastName=@LastName,
Phone=@Phone,
Email=@Email
whereCustomerID=@id
publicstaticvoidexecuteUpdate(Customerc)throwsSQLException{
{callUpdateOneRecord(?
Object[]params={c.getID(),c.getFirstName(),c.getLastName(),c.getPhone(),c.getEmail()}
子模块3:
调用存储过程删除单条记录
createprocedureDeleteOneRecord
@IDint
deleteCustomer
whereCustomerID=@ID
publicstaticvoidexecuteDelete(intID)throwsSQLException{
QueryRunnerqr=newTxQueryRunner();
{callDeleteOneRecord(?
qr.update(sql,ID);
子模块4:
调用存储过程查看顾客
createprocedureShowRecord
select*fromCustomer;
publicstaticList<
Customer>
executeShow()throwsSQLException{
{callShowRecord}"
List<
User>
allList=qr.query(sql,newBeanListHandler<
(Customer.class));
returnallList;
子模块5:
调用存储过程查询在指定时间段内销售订单统计数据
运行截图:
createprocedureQueryData
@sdatedate,
@edatedate
selectC.CustomerID,N.全名,Phone,T.订单个数,T.税后总金额
fromCustomerC,
(select
CustomerID,count(SaleID)as'
订单个数'
sum(Price*(1-Tax))as'
税后总金额'
fromSales
whereSaleDatebetween@sdateand@edate
groupbyCustomerID)T,
(selectdbo.GetName(CustomerID)as全名,CustomerID
fromCustomer
)N--调用函数生成含有全名的临时表
whereC.CustomerID=T.CustomerIDandT.CustomerID=N.CustomerID
orderbyT.订单个数desc,N.全名asc
SalesOrder>
executeSalesData(Stringsdate,Stringedate)throwsSQLException,ParseException{
{callQueryData(?
java.util.Datesddate=newSimpleDateFormat("
yyyy/MM/dd"
).parse(sdate);
java.sql.DatesqlsDate=newjava.sql.Date(sddate.getTime());
java.util.Dateeddate=newSimpleDateFormat("
).parse(edate);
java.sql.DatesqleDate=newjava.sql.Date(sddate.getTime());
params={sqlsDate,sqleDate}
(SalesOrder.class),params);
子模块6:
调用存储过程将指定日期之前进的货进行按指定折扣打折处理
createprocedureDiscount
@Datedate
selectP.ProductID,PName,P.Priceas'
原价'
D.折后价,PurchaseDate
fromProductP,
(selectProductID,Price*0.7as'
折后价'
fromProduct
wherePurchaseDate<
@Date)D
whereP.ProductID=D.ProductID
Product>
executeDiscount(Stringdate)throwsSQLException,ParseException{
{callDiscount(?
java.util.Dateudate=newSimpleDateFormat("
).parse(date);
java.sql.DatesqlDate=newjava.sql.Date(udate.getTime());
Object[]param={sqlDate};
returnqr.query(sql,newBeanHandler<
(Product.class),param);
五.实验中的问题及心得
这次实验是对上次实验的代码化,使用jdbc来调用数据库的存储过程。
实验中运用了连接池来管理连接,达到连接的复用性,提高了软件的性能。
在学习存储过程之前我只会对数据库进行最基本的增、删、改、查操作,一些业务完全是依靠于数据库的基本操作来完成的,学习过存储过程和自定义函数之后,发现业务可以放在数据库中来实现,这样做的好处就是减少对数据库的访问次数,从而达到代码的优化。
在实验的过程中使用了commons组件中的dbutils,但是调用存储过程在Java中使用的是CallableStatement接口,而QueryRunner类中使用的是PrepareStatement接口,这样做会不会出现问题呢?
于是我就查看了JavaSE的帮助文档,发现CallableStatement是PrepareStatement的子接口,但是CallableStatement接口中并没有execute()方法和executeQuery()方法,也就是说这两个方法是父接口的,而且里面的设置参数的方法也是父接口的,这样的话基本上可以用父接口PrepareStatement替代了。
所以QueryRunner类还是可以使用的。
实验中用了自己写的JdbcUtils工具类来管理连接连接池中的连接,而且自己写了TxQueryRunner类来包装父类,这个类重写了父类QueryRunner中所有无Connection参数的方法,然后调用父类的有Connection参数的重载方法,其中Connection通过自己写的JdbcUtils工具类来获取连接。
这样做的话对数据库的操作只需要提供sql语句的模板和参数即可,不需要考虑连接的问题,代码量大大的减少。