数据库操作
1、DAO模式 ---- 数据访问对象
将持久层实现完全封装起来(不需要让调用者知道我是使用什么技术实现持久层的)
所有的数据持久化操作都通过对象来完成
save(User)
delete(User)
update(User)
User find(id)
List<User> findAll
验证:我是否完全按照DAO模式编程---- serlvet中不允许有任何和数据库相关的东西!
2、PrepareStatement 用来替代Statement 来防止SQL注入
先编译sql(预编译),后传入参数
select * from users where name=? and pwd=?; ---- 传入数据库进行遍历 ?只能用来替代变量
select ? from ? where ? = ? and ?= ?; ---- 无法编译,表名、列名这些都不可以用?代替
为什么能防止SQL注入?
select * from users where name='zhangsan' or'1' = '1' and pwd='xxx'; // 在编译时 or会作为关键字进行编译----注入
select * from users where name=? and pwd=?; 编译
username --- > zhangsan' or '1'='1 ------ username中or会作为值的一部分进行处理,不会作为关键字 ----- 防止注入!
编写CustomerCURD程序
1、数据库、数据表
* 在企业内,会选择新建一个数据库,新建一个用户(密码)----来管理这个系统
新建数据库
create database customer
新建数据表
CREATE TABLE `customers` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(20) NOT NULL,
`gender` varchar(10) NOT NULL,
`birthday` date default NULL,
`cellphone` varchar(11) default NULL,
`email` varchar(50) default NULL,
`preference` varchar(100) default NULL,
`type` varchar(10) NOT NULL,
`description` varchar(255) default NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2、准备开发环境
新建web工程 -- day9_customer
导入数据库驱动 --- WEB-INF/lib
新建目录结构
cn.itcast.customer.dao ---- 存放所有数据库操作DAO类
cn.itcast.customer.vo ---- 存放所有数据库表对应值对象
cn.itcast.customer.util ---- 系统所有的工具类
cn.itcast.customer.servlet ---- 存放所有Servlet程序
3、开发
a、客户信息增加功能
编写一个客户信息增加 add.jsp
编写一个客户信息增加 AddServlet
编写一个客户信息存储类 Customer
编写一个客户信息DAO操作类 CustomerDAO
b、编写客户信息查询功能
**个人开发习惯 1.写页面 2.写DAO 3.测试 4.写Servlet
当查询到所有客户信息 通过Servlet输出表格时,麻烦!!!! ----- JSP:html文件中可以通过<%%>写java语法
1)通过request.setAttribute 和 RequestDispatcher.forward 跳转传递数据
JSP内部
<%
List<Customer> customers = (List<Customer>)request.getAttribute("customers");
%>
2)JSP 引包???
<%@page import="java.util.List" %>
<%@page import="cn.itcast.customer.vo.Customer" %>
3)嵌套了java和html jsp页面中的循环
<%
for(Customer customer:customers){
%>
<tr>
<td>xxx</td>
</tr>
<%
}
%>
4) 使用java语法向页面输出 :html: <%= XXX %> ============== java: <% out.print(xxx); %>
out.print("男"); ==== <%="男"%>
5) 对于enum类型,可以通过修改toString() 完成输出!
vip {
@Override
public String toString() {
return "钻石用户";
}
}
插入的时候,不能使用enum的toString 这里会插入中文到数据库
这个时候 enum name方法
customer.getType().name()
c.删除功能
1、页面链接怎么写
<td><a href="del?id=<%=customer.getId() %>">删除</a></td>
2、删除时提供确认 js
<a href="del?id=<%=customer.getId() %>" onclick="delConfirm();">删除</a>
当点击删除时,会触发href和onclick 两个事件,onclick会先被触发
在onclick询问用户是否确认,如果确认,删除,如果用户取消,在onclick中阻止href事件
function checkJump(event){
if(event&&event.preventDefault){ // 阻止其它浏览器跳转
event.preventDefault();
}else{ // 阻止IE跳转
window.event.returnValue = false;
}
}
d.修改功能
1) ViewServlet查询出你要修改那条数据 id --- select * from customers where id = ?
2) 查询出的数据显示在form表单里 view.jsp
input text/password/hidden value="<%=xxx %>"
textarea <textarea><%=xxx%></textarea>
input radio/checkbox <% if... checked='checked' %>
select <option <% if... selected='selected' %>>
提供一个表单隐藏域:用来存放记录的id
3) UpdateServlet 接收更新的数据,调用DAO保存
接收时:定义了Converter、BeanUtils.populate、如果不满足populate列,可以自己手动封装例如:Preference
4) CustomerDAO.update 方法中,要更新所有的数据!!
思考:在删除和修改后,不跳转到主页,而直接显示结果??
在删除DelServlet执行后,直接调用SearchServlet
resp.sendRedirect("search");
BeanUtils ---- 封装时候,只能支持基本数据类型和String,如果不是自定义Converter
封装的时候,表单的字段name属性,必须和JavaBean属性 同样名字,才能自动封装
BeanUtils.populate(Object,Map);
敏捷:极限编程XP、测试驱动、快速部署、scrum ---- 快速迭代模型 3个月内快速迭代下面过程多次
按照功能开发集成! 可持续集成,任意一个时间点 系统都是可用的
传统:RUP 瀑布模型 需求---分析---设计---编码---测试---实施---运维 3个月
JDBC 处理大规模数据
Text 、Blob 存储大规模数据
Text(Clob) 大规模文本数据 ---- 大的文档
Blob 大二进制文件 ----- 电影、图片
编写Clob练习
mysql> create table notes(id int not null primary key auto_increment,content longtext);
编写Blob
mysql> create table images(id int not null primary key auto_increment,content longblob);
测试batch使用
mysql> create table users(id int not null primary key auto_increment,name varchar(20));
String sql = "insert into users values(null,'lisi')";
String sql2 = "insert into users values(null,'wangwu')";
stmt.addBatch(sql);
stmt.addBatch(sql2);
stmt.executeBatch();
在数据库操作中,测试过性能,什么最浪费性能?
创建和关闭连接!
**使用Statement批处理,不可以使用预编译SQL语句
Insert into user(name,password) values(‘aa’,’111’);
Insert into user(name,password) values(‘bb’,’222’);
Insert into user(name,password) values(‘cc’,’333’);
Insert into user(name,password) values(‘dd’,’444’);
如果使用预编译 insert into user values(?.?); 只需要编译一次
采用Statement.addBatch(sql)方式实现批处理:
优点:可以向数据库发送多条不同的SQL语句。
缺点:SQL语句没有预编译。当向数据库发送多条语句相同,但仅参数不同的SQL语句时,需重复写上很多条SQL语句
**想使用预编译执行批处理
采用PreparedStatement.addBatch()实现批处理
优点:发送的是预编译后的SQL语句,执行效率高。
缺点:只能应用在SQL语句相同,但参数不同的批处理中。因此此种形式的批处理经常用于在同一个表中批量插入数据,或批量更新表的数据。
获得数据库自动生成的主键
通过PrepareStatement 不可以直接用Statement
conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS );
ResultSet rs = pstmt.getGeneratedKeys();
System.out.println(rs.getObject(1));