软件开发的过程:
1、需求分析(25-30%):在面试时说明自己参与了某个项目的某个模块从需求到设计到开发的所有过程,
一定客户签字认可,在合同要说明验收时以需求说明书的内容为准,
若有改动,需与商务另行商议。
成果:
需求说明书,具体内容如下:
demo(界面原型):需求的可视化
需求特征列表:简要的说明系统的功能,确定优先级及风险度
用例图(user-case图):说明系统整体的功能
角色:
角色:系统的参与者
用例:一个功能
系统边界:功能范围
关系:
角色与角色:泛化(实线+三角)
用例与用例:
扩展:---extend-->可用可不用
包含:---include---->必须调用
角色与用例:调用(实线+箭头)
用例与角色:通知(实线+箭头)
用例说明:
1、用例流程图(活动图)说明
开始
结束
状态
处理
判断
分支
泳道
汇集
2、写用例说明文档,其有六大元素
功能描述:用例的简要描述
参与者:角色
前置条件:前提
后置条件:结果
基本流:最正常的情况
扩展流:可能及出错的情况
2、整体设计(20-30%)
1、分析业务流程:系统功能及复杂用例的流程
bbs
登陆注册
浏览、发新帖、回复
短消息
用户管理
版块管理
帖子管理
2、根据业务流程设计业务实体及类图(体现ooa思想、数据库设计的思想)
讨论区(1) 版块(0..n)
版块(1) 主帖(0..n)
主帖(1) 回帖(0..n)
用户(1) 帖子(主帖、回帖)(0..n)
用户(1) 消息(0..n)
e-r图的的过程
1、外模型:根据业务找业务实体,与具体技术无关
2、概念模型:与具体的技术整全在一起
过程:
找实体
接关系
写属性
三级范式:
有主键
完全依赖于主键
不出现传递依赖
类图:
角色:
接口
类
关系:
继承:实线+三角
依赖:虚心+箭头
实现接口:虚心+三角
关联:实线+箭头
聚集:实线+空心菱
组成:实线+实心菱
3、确定项目的技术框架
框架设计的原则:上层依赖于下层,尽量减少下层对上层的
依赖,层与层之间通过接口调用。
模式的目的:提高代码的可扩展、可维护性
模式的原则:增加开放,修改关闭,面向接口抽象类编程
常用的模式:
最好画图
simplefactory:简单工厂,有三个角色
工厂:产生具体产品返回抽象产品
抽象产品:一个接口或抽象类
具体产品:具体的实现
增加一个产品时不用修改客户端,只需修改工厂,
如果用了返回,就不用修改工厂,只需修改配置,spring
用的就是返射,是超级工厂。
单例:整个虚拟机中只有一个实例。三大特征:
1、私有所构造子
2、私有的静态属性
3、公有的静态方法,对象为空时产生一个新的,
不为空直接返回
代理:代理与真实对象实现的是同一接口,将真实对象作为代理的属性
向客户端公开的代理,客户端调用代理的方法时,代理找到真实对
象,调用真实对象方法,在调用之前之后通过装备可以提供事务、
日志、安全等服务。
模板:父类提供抽象方法及具体方法,具体方法调用抽象方法,
抽象方法由子类实现,向客户端公开的子类,客户端通过
父类的具体方法调用子类实现的抽象方法,为子类
提供服务。
装饰:有三个角色,通用接口,本原,装饰,将通用接口聚集到装饰中,
装饰可以有很多子类,可以将本原或装饰通过构造子注入到另一
个装饰中,将多个装饰的功能随意组合。
轻量级的框架
jsp&servlet&dao&jdbc:用的model2,速度是最快的,开发效率不高。
M:
facade&dao&jdbc
C:
serlvet
V:
jsp
通过jsp将请求发给servlet,servlet通过
FacadeFactory产生具体的Facade返回一个IFacade接口,通过IFacade接口
调用Facade的具体方法。
Facade通过dao的抽象工厂产生具体的工厂,通过具体的工厂产生具体的dao,
返回dao接口给业务层。
Facade执行完后将结果返回给servlet,servlet转发到下一个页面。
Servlet用了模板模式可以提供错误处理、事务、页面跳转的服务。
struts&dao&hibernate:速度较快,因为我们要自己实现工厂,并不是所有的一切
都是返射,相对spring来说速度更快一些。
struts:
mvc,请求处理过程
用一个模板模式提供通用错误、事务、跳转服务。
将IFacade接口作业其属性,通过FacadeFactory工厂产生具体的Facade
返回一个Facade接口。
facade
IFacade接口
Facade实现类
FacadeFactory:facade工厂
dao接口作为Facade的属性,通过AbstractFactory调用具体的DaoFactory
产生具体的dao实例,返回dao接口。
dao:
dao
daoImpl
DaoFactory:产生daoImpl实例,返回dao接口
AbstractFactory:通过返射、工厂、单例产生具体的DaoFactory,返回
AbstractFactroy给业务层,因为具体的工厂继承于抽象的工厂,
客户端调用的还是具体工厂方法。
hibernate
核心类
核配置文件
struts&spring&hibernate/ibatis:这是当前最通用、最快速、藕合度最低的开发方式
但也有一个问题spring一切都是返射,速度慢。
struts/hibenate/ibatis要解析xml文件、要大量用到返射,所以速度慢。
一般适合于中小型系统(并发量<500),大型系统有些不适合需要调整。
struts已是MVC
spring是一个超级工厂,在spring中配置的都是实现类,在代码中得到都是接口。
hibenate/ibatis是o/r Mapping
框架结构:
struts:
mvc
请求处理过程
在spring中加入bean标签,配置具体的action,通过set方法将Facade代理
注入到action的IFcade接口中。
Facade
IFacade接口
Facade实现类
在applicationContext.xml配置具体的Facade类,在配置Facade的Aop服务时,
先配置抽象代理AbstractProxy其类是TransactionProxyFactoryBean,说明装备
TransactionManager,说明连接点TransactionAttributes。再配置具体的
代理,继承于AbstractProxy,通过target指向真实的对象。
通过set方法注入将具体的Dao注入到Facade的Dao接口属性中。
Dao
dao接口
dao的实现 extends HibernateDaoSupport/SqlMapClientSupport
在applicationContext.xml中配置具体的dao,向Facade返回dao接口。
hibernate
在applicationContext.xml中配置dataSource、sessionFactory,
通过set方法注入将sessionFactory注入到dao实现类中。
ibatis:
在applicationContext.xml中配置dataSource、sqlMapClient,
通过set方法注入将sqlMapClient注入到dao实现类中。
3、详细设计
对于开发能力比较强的团队,可以不做详细设计。
时序图:
作用:找类、找方法、验证系统的正确性
元素:
纵轴:时间、对象的生命周期
横轴:说明对象与对象的交互
4、编码(25-30%)
5、测试(10%)
uml
ooa与ood的区别?
ooa:面向对象的分析,根据客户的业务找业务实体,与具体的技术无关,客户可以看懂。
ood:面向对象的设计,是ooa的全集,与具体的技术框架相结合进行设计。
面向过程与面向对象的区别?
面向过程:
1、现实世界是对象,其在分析过程中是对象,
在设计过程不是对象而是方法与方法之间的调用,
容易与现实脱离,容易出错。
2、因为是方法与方法之间的调用,重用性不高,
无法达到宏观层次上的控制。
3、开发难、维护难、可扩展性、重用性差。
面向对象:
1、现实世界是对象,其在分析过程中是对象,
在设计过程还是对象
分析设计与现实接近,降低了开发的难度。
2、继承可以让概念在宏观层次重用,当层与层之间通过
接口或抽象类调用时,他们所依赖的不再是具体的实现
细节,而是宏观商业逻辑即接口、抽象类,具体的实现
是可以随时被替换的。
3、技术在不断的更新,但业务变化较少,
业务实体可以很好的重用。
3、开方方便、好维护、好扩展
什么是模型?现实的浓缩。
模型的作用?
1、便于分析、认识世界
2、便于存档、沟通
3、便于决策。
模型的原则?
1、模型好坏决写系统的成败。
2、与现实越接近说明模型越正确。
3、模型不止一个,而是多个,它从不同的侧面说明现实的世界。
4、根据不同人的需求,模型有不同的实现细节。
九大图形:
类图:贯穿软件开发的所有过程,从需求到整体到详细到开发到测试,
是uml中最重要的图形,在ooa阶段中找业务实体,在ood阶段中
将业务实体与具体技术结合起来设计操作类及实体类
use-case:是系统分析员与客户沟通的桥梁
时序:说明在时间点上类与类之间的交互,主要用于整体及详细设计阶段,
作用是找类、找方法、验证系统的正确性
活动图(流程图):用于需求阶段说明具体业务的流程
协作图:说明类与类之间的交互,与时序图功能类似,但没有时间的概念,
通过序号说明交互顺序。
状态:一个对象在不同方法的操作下状态的改变。
元素:
对象
方法
构件:说明组件与组件或层与层之间的依赖关系。
元素:
组件
部署:说明主机与主机之间的关系,找出系统运行的瓶颈。
元素:
主机
对象图:不般不画
活动图作用及元素?
主要用在需求分析阶段,说明某一个用例的业务流程。
元素如下:
开始
结束
状态
处理(动作)
判断
分支:一个操作转化为多个操作
汇集:多个操作转化为一个操作
泳道:说明不同角色所做的工作
软件开发的过程模型:
1、瀑布模型
前一个阶段结束并审核通过后才可以开始下一个阶段
缺:
不灵活、不适合大型、需求模糊的系统
2、螺旋模型:迭代式,每一次迭代要将软件开发的流程再走一遍。
优:
灵活、适合大型、需求模糊的系统
缺:
太灵活无法保证质量
3、统一软件开发流程(rup):有四大阶段六大流程,每一个阶段
都会执行六大流程。每一个阶段所执行流程的侧重点不一样。
四大阶段:
启动:侧重于需求
精化:设计
构建:编码
产品化:部署
六大流程:
业务建模:找业务实体及业务实体之间的关系
需求:
分析设计
实施:编码
测试:
部署
4、极限编程(xp):
侧重点:
1、有效的沟通胜过合同谈判
2、高质量的代码胜过面面俱到的文档
3、成对开发
4、迭代
jsp&servlet
1、jdbc中的核心类
Class.forName("com.microsoft.");//注册驱动
DriverManager:得到连接
Connection con=DriverManager.getConnection("jdbc:microsoft:sqlserver://localhost:1433;databaseName=pubs;selectMethod=cursor","用户",“密码”);
Connection:一个连接会话,可以得到执行sql的对象
--执行dml(insert update delete)
PreparedStatement ps=con.preparedStatement("insert into student values(?,?,?)");
ps.setString(1,"张三");
ps.executeUpdate();
Statement st=con.createStatement();
--执行查询
st.executeQuery("select * from student");
--执行dml(insert update delete)
st.executeUpdate("insert into student values('cc','cc','x','s')");
--执行查询
PreparedStatement ps=con.preparedStatement("select * from student");
ResultSet rs=ps.executeQuery();
PreapredStatement、Statement的区别
PreparedStatement:
可以动态传参
在得到PreparedStatement实例时,要给定sql,所以sql是预编译,重复执行时效率高。
Statement
不可以动态传参
在得到Statement实例时,不给定sql,sql不预编译,重复执行时效率低。
2、如何实现一个servlet
1、继承于HttpServlet,实现doGet及doPost方法
public class MyServlet extends HttpServlet
{
//form中的method=get时或超链时调用doGet方法
//doGet的信息写在请求的url中,不安全,传输的信息少
//如果是表单一般用doPost方法
public void doGet(HttpServletRequest request,HttpServletResponse response)
{
request:客户的请求及表单域信息
//表表单域信息
String userName=request.getParameter("表单域名");
String like[]=request.getPrameterValues("重复的表单域名");
//在request中加入对象,转发到另一页面时可以重用
request.setAttribute("名称","对象");
request.getAttribute("名称");
//转发到另一个servlet或jsp页面,会通过参数将当前servlet或jsp中的request
response传入到另一个页面
request.getRequestDispatch("a.jsp").forward(request,response);
//得到session
HttpSession session=request.getSession();
response:是响应信息
//得到输出流,向客户端打印文本
PrintWriter pw=response.getWriter();response.getOutputStream();
pw.println("<h1>helloworld</h1>");
//跳转:下一个页面或servlet不保留上一个页面的request、respose对象。
response.sendRedirect("a.jsp");
}
//form中的method=post时调用
//doPost的信息写在http请求的正文中,安全,传输的信息大
//如果是表单一般用doPost方法
public void doPost(HttpServletRequest request,HttpServletResponse response)
{
}
}
在web.xml部署
<servlet>
<servlet-name>myServler</serlvet-name>
<servlet-class>servlet.MyServlet</servlet-claass>
</servlet>
<servlet-mapping>
<servlet-name>myServler</serlvet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
3、转发、跳转、提交、超链的区别
转发:运行在服务端,下一页面保留当前页面的request、response
跳转:运行在服务端,下一页面不保留当前页面的request、response
提交:运行在客户端,向服务器发送请求,提交表单域的内容
超链:运行在客户端,向服务器发送请求,提交超链信息
4、jsp中的九大内置对象
request:HttpServletRequest,转发到下一个页面时可以重用对象
response:客户端响应
session:HttpSession,一个用户多个页面共享同一变量。
application:ServletContext,多个用户多个页面共享同一变量。
pageContext:jsp页面的运行环境,在自定义标签中用的很多,
可以得到另外8大对象
pageContext.getRequest();
pageContext.getApplication();
--转发到另一个页面
pageContext.forword("a.jsp");
request.getRequestDispatch("a.jsp").forward(request,response);
out:向客户端打印文本
out.println("<h1></h1>");
exception:只在异常页面中,正常页面出错时跳到异常页面,通过异常
页面显示错误。
异常页面(error.jsp)
<%@page isErrorPage="true"%>
exception.getMessage();
正常页面(common.jsp):
<%@page errorPage="error.jsp"%>
page:当前jsp页面内有效,作用域最小
config:ServletConfig的实例,代理当前jsp页面的配置
5、servlet的体系结构
Servlet接口
GenericServlet通过用Servlet可以跨协议
HttpServlet:只适用到http协议
自定义Servlet,必须继承于HttpSerlvet
6、servlet生命周期
1、单例
2、3个方法
init:初始化时调用,只调用一次
service:每请求一次调用一次
doGet
doPost
destroy:销毁时调用,只调用一次
7、动作:
<jsp:forward page="sucess.jsp"/>转发到另一个页面
<jsp:include page=""/>导入另一个页面的运行结果
<jsp:userBean id="" class="" scope="request/session/application"/>
有则用已有的,没有则产生一个新的
<jsp:setProperty name="" property="" value=""/>:向一个对象的一个属性设值
<jsp:getProperty name="" property=""/>:打印一个对象的属性值
8、指令
<@page import="" contentType="text/html;charset=utf-8"
isErrorPage="false/true" errorPage="error.jsp"/>
<@taglib uri="" prefix=""/>//引入标签库
<@include file=""/>//将两个页面合在一起形成一个文件,编译成class运行。
9、model2(MVC)的处理过程
MVC
M(model):
StudentPersistent(Dao)
V(view)
jsp
c(control)
Servlet
请求处理过程:
jsp--->serlvet-->studentPersistent
studentPersistent-->servlet--jsp
10、model2的作用:
让模型与视图强制解藕,相当到旅店的服务员,提高了
代码的可扩展、可维护
11、el语言及jstl标签
显示信息
${requestScope/sessionScope/applicationScope.user.userName}
循环
<c:foreach items="${requestScope.users}" var="user">
${user.userName}
</c:foreach>
判断:
<c:if test=${requestScope.user.userName=='a'}>
</c:if>
在jsp页面中不出现任何的%,只有el及标签,这样页面没有任何逻辑
只有显示作用。
12、过滤器的作用:是一个拦截器可以拦截所有的请求,在调用jsp或servlet之前
执行,jsp或serlvet执行完后再次过滤处理。相当于门,进
与出时都可过滤处理。
public class MyFilter implements Filter
{
public void doFilter(HttpServletRequest request,HttpServletResponse response,Filter filte)
{
request.setCharactorSet("utf-8");
filter.doFilter(request,response);//给真正的处理者
System.out.println("aaaaaaaaaaaaaaa");
}
}
<filter>
<filter-name>code</filter-name>
<filter-class>aa.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>code</filter-name>
<url-pattern>/*.do</url-pattern>
</filter-mapping>
struts1
1、struts的MVC分别代表那些类?
M:业务+dao+持久
V:jsp actionForm
C:
ActionServlet:接收所有以.do结尾的请求
RequestProcessor
Action:做具体的业务处理
ActionMapping:封装action标签中的所有内容,通过url打开action、actionForm,
通过名称找到actionForward
ActionForward:转发到另一个页面
2、struts的请求处理过程?
url.do将请求发给ActionServlet
ActionServlet转发给RequestProcessor
RequestProcessor根所url在struts-config.xml找到对应的Action及ActionForm
如果在相关的作用域中存在ActionForm,RequestProcessor用已有的,如果不存,
RequestProcesor实例化一个新的,并通过类的返射将表单域的值注入到ActionForm中
如果存在Action,RequestProcessor用已有的,如果不存在实例化一个新的Action并
调用Action的execute方法。
execute方法执行结束时通过ActionMapping找到一个ActionForward转发到另一个jsp页面。
3、struts原理
struts的核心类是ActionServlet,其可以接收所有.do结尾的请求。
核心配置文件是struts-config.xml文件说明url与Action及ActionForm
的对应关系,url不可以重复。
在web.xml中说明ActionServlet、其可以接收所有以do结尾的请求;
说明struts-config.xml所在位置,以参数的形式传给ActionServlet。
当启动容器时,容器(tomcat、weblogic)实例化ActionServlet,初始化
ActionServlet,在初始化ActionServlet时加载struts-config.xml文件。
当客户通过url.do将请求发给ActionServlet,ActionServlet将处理
转发给助手RequestProcessor,RequestProcess通过struts-config.xml
找到对应的actionForm及action,如果有ActionForm用已有的,没有
通过类的反射实例化一个新的ActionForm,放置到作用域对象,通过反射
将表单域的值填充到actionForm中。如果有Action用已有的,没有产生
一个新的,通过反射调用action的execute方法,在执行前将actionForm
通过参数注入到execute方法中,execute方法执行结束前通过actionMapping
找到actionForward转发到另一个页面。
4、RequestProcessor的处理过程
processPath() 确定选择将要处理的动作的路径
processMapping() 为请求选择动作映射
<action path="/login" type="struts.action.LoginAction"
name="userForm" attribute="userForm"
scope="session" input="/login.jsp" validate="true"
>
<forward name="success" path="/succ.jsp"/>
<forward name="error" path="/error.jsp"/>
</action>
processActionForm() 新建一个 Form Bean 或从请求会话中检索 Form Bean
processPopulate() 填充与请求关联的 ActionForm
processForward() 处理 <action-mapping> 元素的 forward 以匹配当前的请求路径
processValidate() 调用 Form Bean 的 validate() 方法
processActionCreate() 实例化当前 ActionMapping 指定的类的实例
processActionPerform() 将调用 action 的 perform() 或 execute() 方法
processPreprocess() 告诉请求处理器调用此方法后是否应继续处理请求
5、struts的标签库
<html>
<html:select property="">
<html:options/>
</html:select>
<html:radio>
<html:mulitibox value="" property="字符串数组">
1、错误返回的页面可以保留以前的值。
2、前一个action产生的form如果在request或session中,
转发到另一个jsp页面,jsp页面所用的form与前一个action
所用的form名称及类型相同可以直接显示
<bean>
<bean:define name="" id="" scope=""/>
从scope中取出name放到变量id中。
<bean:define id="" scope="" name="" property="属性名"/>
从scope中取出name的property属性放到变量id中。
<bean:write name="" property=""/>
将对象name的值打印。
<bean:message key=""/>
通过键名取国际化的值
<logic>
<logic:iterator id="" scope="" name="" />
从scope中取出集合name将其每一个元素放到id中。
<logic:iterator id="" scope="" name="" property=""/>
从scope中取出对象name的property属性值(集合),将其每一个元素放到id中。
<logic:present name="" scope=""/>
在scope中是否存在name对象
<logic:equal value="01" name="user" property="sex">
6、struts的国际化:不用修改源代码只加入一个properties文件实现国际化
一、资源文件:名称_语言_国家.properties
message_en_US.properties
message_zh_CN.properties
如果有非英语或数字,需将资源文件转码native2ascii -encoding utf-8 源 目
二、在struts-config.xml指定资源文件的名称:包名+文件名(struts.message)
三、在jsp中<bean:message key=""/>通过键名加载相关的消息。
7、action的分类:
一个Action只能有一个execute方法
DispatchAction:可以有多个方法
public 类 extends DispatchAction
{
public void add()
{}
}
<action
attribute="loginForm"
input="/login.jsp"
name="loginForm"
path="/login"
scope="request"
validate="true"
type="struts.action.LoginAction" parameter="表单域名" />
8、加载多个struts-config.xml
在web.xml中修改ActionServlet的参数配置,对于config参数
其指向的文件不再是一个struts-config.xml文件,而是多个
struts-config.xml文件,如
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/config-1.xml,/WEB-INF/config-2.xml</param-value>
</init-param>
9、form的分类
1、继承于ActionForm,必须写一个
2、动态form,没有类,而是将其名称及数据类型写入到了struts-config.xml文件中
动态form就是一个Map,每次从这个map中取属性值。
hibernate
1、作用:
O/R Mapping 执行速度慢、将工作量降底95%
2、核心配置文件
hibernate.cfg.xml:数据库的连接、 批量处理、加载二级缓存驱动、显示sql
*.hbm.xml:将一个表与类相映射、二级缓存的方式
3、核心接口及类
类:
Configuration:读取hibernate.cfg.xml及*.hbm.xml文件
接口:
SessionFactory:产生具体的session
Session:做具体的操作
save
update
saveOrUpdate:有主键修改,没主键增加
delete
load
Transaction :事务处理
Transaction trans=session.beginTransaction();
trans.commit();
trans.rollback();
Query:执行查询
//hql,类及属性是对象
Query query=session.createQuery("from Customer where customerid=:aa")
query.setString("aa","aa")
List list=query.list();
Validator:在做之前进行拦截,在处理之前进行校验
Lifecycle:拦截器,可以增加、修改、查询等之前触发,但其让数据类与
hibernate的藕合度增加,一般不用。
public class Users implements Validator,Lifecycle
{
}
interceptor:拦截器,其比Lifecycle更加的优秀,不用每个数据类去实现一些
接口,而是在产生session时将其注入到session中。
其可以增加、修改、查询等之前触发,但其中的session不可以重用,
可以用上一个session的connection,不用管事务,因为事务已被
前一个session实现。
4、关联:
one-to-many
get/set方法
一方通过get方法可以取出另一方,另一方也可以通过get方法取出对方,
所以在one这边有一个Set属性可以得到所有的many,many这边有一个One类型
的属性可以取出one
inverse:主控方,维护外键值,说明外键列由谁来控制,要想维护外键列的值
必须将被控方作为主控方的属性,主控方一般在many方。
inverse=false 是主控方,外键是由它控制的
inverse=true 是被控方,外键与它没关系
cascade:级联,要想实现级联必须将从对象作为主对象的属性。
主表增从表增
主表修从表修
主表删从表删
lazy:延迟
lazy=false:不但取当前对象,还取其关联的所有内容
lazy=true:只取当前对象不取关联对象的属性,当真正
用到对方属性时才执行sql加载相应的值
4、批量删除
Query query=session.createQuery("update"或"delete");
query.executeUpdate();
不同步缓存
5、Tomcat连接池:
在容器中预先产生了n个连接实例,客户端不用重新实例化,可以直接取
用完后还可以放回去。
1、 将sql-server三个包拷贝到C:/tomcat-6/lib下目录下
2、修改C:/tomcat-6/conf/context.xml为以下内容
<Context path="/chap0" docBase="chap0"
debug="5" reloadable="true" crossContext="true">
<Resource name="jdbc/sqlserver" auth="Container" type="javax.sql.DataSource"
maxActive="100" maxIdle="30" maxWait="10000"
username="sa" password="" driverClassName="com.microsoft.jdbc.sqlserver.SQLServerDriver"
url="jdbc:microsoft:sqlserver://localhost:1433;databaseName=pubs;selectMethod=cursor"/>
</Context>
jdbc测试代码
Context initCtx = new InitialContext();
//进入连接池环境
Context envCtx = (Context)initCtx.lookup("java:comp/env");
//得到一个连接池
ds = (DataSource)envCtx.lookup("jdbc/sa");
//得到连接
Connection conn = ds.getConnection();
hibernate通过连接池实现连接
<session-factory name="foo">
<property name="connection.datasource">java:comp/env/jdbc/sa</property> <!--指定tomcat连接池-->
<property name="show_sql">true</property> <!--是否显示sql-->
<property name="dialect">org.hibernate.dialect.SQLServerDialect</property> <!--hibernate的驱动管理器-->
<mapping resource="com/accp/t15/Customer.hbm.xml"/>
</session-factory>
spring调用tomcat中的连接池
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>java:comp/env/jdbc/name</value>
</property>
</bean>
6、hibernate中的主键生成机制:
1) Assigned:手动给定
5) identity:sqlserver、db2、mySql的自动增加
6) sequence:oracle的序列
7) native:自动选择identity、sequence,不用手动给定
8) uuid.hex:Hibernate基于128位唯一值产生算法生成16 进制数值
7、数据库开发的过程
外模型
以客户为中心,客户可以看懂。
概念模型
以外模型作为输入,适应开发的进一步细化,是外模型全集
注意事项:
符合需求
速度
冗余
开发的难度
内模型
数据库
8、e-r图设计的过程
找实体
拉关系
写属性
9、三级范式
主键
projectID projectName empID empName 职务 小时工资 工时
完全依赖于主键
--project
projectID projectName
--emp
empID empName 职务 小时工资
--工时
工时 projectID empID
不出现传递依赖
--project
projectID projectName
--emp
empID empName 职务
--工时
工时 projectID empID
--职务
职务 小时工资
10.对象的三大状态
自由(transient)
与session无关,直接实例化一个对象
持久(persistent)
由session来管理
在持久状态中通过get方法取出对方
游离(detached)
被session抛弃
11、没有锁出现的问题
1、脏读:一个事务处理的数据是另一个事务没有提交的数据
2、覆盖更新:一个事务将另一个事务的修改覆盖了。
3、不可重复读:一个事务两个相同的sql读取出来的内容不一样。
4、幻想读:同一个事务第一次读有,第二次读没有。
12、锁的分类
1、读未提交:可以读取未提交的数据,不可以防止脏读、覆盖更新。
2、读已提交:(数据库默认的处理方式):读取的数据是已提交的,在提交之前将当前行的版本与数据
库的版本比较,若小于数据库的版本报错回退。
乐观锁:一个游标读取一批数据后不加锁,
另一个事务可以更新游标中的数据,
但游标所在事务更新另一事务更新过的行时,
报错,回退。
系统运行效率快。
悲观锁:一个游标读取一批数据后加锁,
另一个事务不可以更新游标中的数据,
但游标所在事务的更新一定成功。
系统运行效率慢。
3、可重复读:将上一个sql取的数据临时存储,保证同一个事务内下一个
sql与上一个sql取的数据一样。
4、串行化:一个事务对表进行select、update、delete、insert时
全表加锁,另一个事务只可以select不可update、delete、
insert。
速度最慢。
13、hibbernate的缓存有几种
1、事务级(一级缓存 session):当前事务结束缓存结束。
2、应用级(二级缓存 SessionFactory):所有session共享同一个SessionFactory
的数据。要人为让SesionFactory是单例模式。
3、集群(有多个应用服务器):每一台主机有一个SessionFactory,
一个服务器的数据发生改变要通知其它所有服务器
同步缓存数据或删除缓存数据,如果删除,下次取
时再从数据库中取。集群级缓存要慎用,因为有主
机之间有通信,要有socket连接,要同步数据增加网络
流通量及系统开销。
14、利用缓存的原则
数据量在可接收的范围内
更新或并发更新少
重复查询且使用率高的数据
15、缓存的实现
1、hibernate提供了支持缓存的接口,通过修改
hibernate.cfg.xml设置缓存。
2、将ehcache.jar拷入工程
3、要src的根目录下加入ehcache.xml说明缓存。
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd">
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>
</ehcache>
3、在hibernate.cfg.xml中加入两个属性
a、说明提供二级缓存驱动类
b、说明query也支持缓存
<property name="hibernate.cache.provider_class">
org.hibernate.cache.EhCacheProvider
</property>
<property name="hibernate.cache.use_query_cache">true</property>
4、在具体的hbm.xml中说明当前类使用二级缓存
<cache stage="read-only"/>
5、在执行query之前设置其支持二级缓存
query.setCacheable(true);
16、list使用缓存的特点:
sql只执行一次,直接查询o/r mapping后返回结果,要想重用缓存,hql必须相同,如果相同,
相应行的主键在缓存中就直接取,如果没有根据主键值在数据库中找,而不是重新执行整个sql。
17、iterator使用缓存的特点:
先执行一次sql取出所有主键,再根据主键值查找缓存,若有直接取出,若没有根据主键
在数据库中查相应的对象并进行o/rMapping。
对于没缓存的sql,其sql要执行 "行数+1"次。对于有缓存的行,执行效率高。
综上:第一次查询用list方法,第二查询用iterator方法。
18、数据查找的过程
首先在一级缓存中中找,若没有找到就在二级缓存中,若还是没有
找到就产生sql在数据据库中找。
19、缓存的特点:
load、get、insert、update、delete都会自动同步缓存,但query.executeUpdate()不更新缓存,
但如果批量更新时exeucuteUpdate执行效率很高。一个对象通过get或query.list()的方法查询
放到一级缓存或二级缓存中时,不能用update直接更新,只通通过set方法更新。
evict:清除缓存。
20、load与get方法的区别
相同点:3.2版本
先从一级缓存找,如果没在二级缓存中找的。
load:
如果没有找到报ObjectNotFoundException异常、返回的是一个代理,
如果当前数据类有接口返回的应是接口、没有则通过CGLIB返回类似接口的引用。
get
如果没有找到返回null、如果有得到是一个真实的对象
21、hibernate常见优化策略
用最新版本的hibernate
制定合理的缓存策略
用二级缓存,缓存的原则。
采用合理的session管理机制
一个线程一个session,线程结束session结束。
尽量使用延迟加载
many
大文本、大文件
设定合理的批处理参数(batch-size)
fetch_size:每次从数据库中取出记录条数一般设置为30、50、100。
OracleJDBC驱动默认的Fetch Size=15,设置Fetch Size为:
30、50性能会明显提升。
batch_size:
在进行插入、更新、删除时执行多少个sql后将sql提交到数据库中
hibernate中的配置如下:
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>
<prop key="hibernate.show_sql">false</prop>
<!-- Create/update the database tables automatically when the JVM starts up
<prop key="hibernate.hbm2ddl.auto">update</prop> -->
<!-- Turn batching off for better error messages under PostgreSQL
<prop key="hibernate.jdbc.batch_size">100</prop> -->
<prop key="hibernate.jdbc.fetch_size">50</prop>
</props>
</property>
如有可能,选用uuid作为主键生成器
如有可能,选用基于version的乐观锁替代悲观锁
悲观锁:
1、
Query query1=session.createQuery("select * from Customer for update");
2、
Query query1=session.createQuery("select * from Customer");
query1.setLockMode("Customer",LockMode.UPGRADE);
乐观锁
<class
optimistic-lock="version/none"
/>
开发过程中,打开hibernate的SQl日志输出(hibernate.show_sql=true),通过观察hibernate生成的sql语句进一步了解其实现原理,
从而指事实上更好的实现策略。
22、hql
1、criteria:可以不用写hql就可查询数据库中的内容
Criteria cri=session.createCriteria(Customer.class);
--加入查询的条件
cri.add(Expression.gt("age",30));
--加入排序
cri.addOrder(Order.desc("sex"));
--分页
cri.setFirstRow(0);
cri.setMaxResultRows(2);
2、取一个属性
List<String> sexes=session.createQuyer("select sex from Customer");
for(String sex:sexes)
{
}
3、取多个属性
List<Object[]> fields=session.createQuyer("select customerName,age,sex from Customer");
for(Object[] field:fields)
{
field[0];
field[1];
field[2];
}
4、将多个属构造成一个对象
List<Customer> customers=session.createQuyer("select new Customer(customerName,age,sex) from Customer");
for(Customer customer:customers)
{
customer.getCustomerName();
}
5、查询的sql来自于配置文件
--在*.hbm.xml文件中配置hql
<class>
</class>
<query name="myHql">
<[!CDATA[
FROM Customer where customerName=:customerName
]]>
</query>
Query query=session.getNamedQuery("myHql");
query.setString("customerName","a1");
query.list();
6、order by及group by
List<Object[]> fields=session.createQuery("
select count(sex),customerName from Customer
group by customerName order by customerName").list();
for(Object[] field:fields)
{
Long count=(Long)fields[0];
String customerName=(String)fields[1];
}
7、关联
1、没有fetch
1、通用的sql
a、在where条件中关联
select c.*,b.* from customer c,buy b
where c.customerName=b.customerName;
b、在from子句中关联
select c.*,b.* from customer c join buy b
on c.customerName=b.customerName;
2、hibernate的实现
1、没有fetch的实现
List<Object[]> results=session.createQuery("from Customer as customer inner join customer.buies");
for(Object[] result:results)
{
Customer customer=(Customer)result[0];
Buy buy=(Buy)result[1];
}
2、有fetch的实现
23、数据加载方式
即时加载:加载不但加载当前对象还加载其关联对象属性
延迟加载:加载时只加载当前对象,不加载关联对象,只有真正用关联对象的属性时
才加载。
预先加载:针对关联,一个sql加载多个对象。
批量加载:设置batch-size及fetch-size参数
24、继承的实现
1、一个类一张表
2、子类与父类是同一张表,在表中多加入一个字段说明是子类还是父类
a、表
create table user2
(
userName varchar(20) primary key,
pwd varchar(20),
guessRemark varchar(20),
adminRemark varchar(20),
DISCRIMINATOR_USERTYPE varchar(30)
)
2、三个类的实现,Guess及Admin继承于user2
3、具体配置
<class name="hibernate.User2" table="user2" discriminator-value="user">
<id name="userName" type="java.lang.String">
<column name="userName" length="20" />
<generator class="assigned"></generator>
</id>
<!--这个列值用于标识不同的类-->
<discriminator column="DISCRIMINATOR_USERTYPE" type="java.lang.String"></discriminator>
<property name="pwd" type="java.lang.String">
<column name="pwd" length="20" />
</property>
<!-- 说明第一个子类-->
<subclass name="hibernate.Guess2" discriminator-value="guess">
<property name="guessRemark" type="java.lang.String">
<column name="guessRemark" length="20" />
</property>
</subclass>
<subclass name="hibernate.Admin2" discriminator-value="admin">
<property name="adminRemark" type="java.lang.String">
<column name="adminRemark" length="20" />
</property>
</subclass>
</class>
4、特点:查询父类时会查询所有的子类
3、三个类三张表,子类对应的表共享父类的字段
1、sql
drop table guest3;
drop table admin3;
drop table user3;
create table user3
(
USERID varchar(32) primary key,
username varchar (30),
pwd varchar(20)
);
create table guest3
(
USERID varchar(32) primary key,
guest_remark varchar(20),
constraint guest3_fk foreign key(userID) references user3(userID)
);
create table admin3
(
USERID varchar(32) primary key,
admin_remark varchar(20),
constraint admin3_fk foreign key(userID) references user3(userID)
);
2、配置
<class name="hibernate.User3" table="user3" >
<id name="userid" type="java.lang.String">
<column name="USERID" length="32" />
<generator class="assigned"></generator>
</id>
<property name="username" type="java.lang.String">
<column name="username" length="30" />
</property>
<property name="pwd" type="java.lang.String">
<column name="pwd" length="20" />
</property>
<joined-subclass name="hibernate.Admin3" table="admin3">
<key column="USERID"/>
<property name="adminRemark" type="java.lang.String">
<column name="admin_remark" length="20" />
</property>
</joined-subclass>
<joined-subclass name="hibernate.Guest3" table="guest3">
<key column="USERID"/>
<property name="guestRemark" type="java.lang.String">
<column name="guest_remark" length="20" />
</property>
</joined-subclass>
</class>
25、many-to-many
create table power
(
powerID int primary key,
powerName varchar(20)
);
create table role
(
roleID int primary key,
roleName varchar(20)
);
create table rolepower
(
powerID int foreign key references power(powerID),
roleID int foreign key references power(powerID)
);
--power
<set name="rolepowerSet" inverse="true" table="rolepower">
<key column="powerID"/> --powerID是rolepower的外键列
<many-to-many class="hibernate.Role" column="roleID"/> --roleID是rolepower的外键列
</set>
--清楚当前power的主键值
select * from Role where rowID in
(
select roleID
from rolepower where powerID=当前power的主键值
);
--role
<set name="rolepowerSet" inverse="false" table="rolepower">
<key column="roleID"/>
<many-to-many class="hibernate.Power" column="powerID" />
select * from Power where powerID in
(select 中间的外键powerID from rolepower where 中间的外键roleID=role表的主键(roleId))
</set>