-------------------------------------1----------------------------------
MVC:Model(JavaBean),View(JSP),Controller(Servlet)
Servlet中跳转到另一个JSP,并且将参数保存在request中,写在doPost中ServletContext application = this.getServletContext();
RequestDispatcher rd = application.getRequestDispatcher("/result.jsp");
rd.forward(request, response);
引入一个自定义类<%@ page import="po.Student"%>
或者:
//////////////有时出现错误,可能是局部对象作用范围的问题,参见Prj1_1里的
SQL模糊查询,LIKE的通配符"_"(一个字符),"%"(任意个字符),汉字是两个字符,所以使用__
eg:SELECT * FROM table WHERE name LIKE '%s%';包含s的所有结果
-------------------------------------2----------------------------------
Struts就是一个基于MVC模式的框架,只是一个编程规范,让大家的代码风格更统一
在Struts中:
1.JSP表单内容首先提交给ActionServlet,ActionServlet将信息打包在ActionFrom中,送给Action(ActionServlet是Struts自带的)
2.ActionServlet不直接处理业务逻辑,让Action来调用JavaBean
3.Action负责决定跳转到另一个JSP,并显示结果(只是决定跳转,但动作还是由底层的ActionServlet做的)
4.配置文件(负责JSP->ActionForm,ActionForm->Action的映射)
需要编写:JSP,ActionForm,Action,配置文件(xml文件,struts-config.xml),JavaBean
////////////首先必须导入Struts支持包,并更爱base package for new calsses
////////////ActionFrom容纳表单提交的值
1。必须继承org.apache.struts.action.ActionForm
2。必须编写和表单元素同名的的属性
3。必须在Struts配置文件中进行注册(让Struts框架认识这个ActionFrom)
////////////Action负责接收ActionFrom传来的数据
1。必须继承org.apache.struts.action.Action;
2。重写execute函数,来处理业务逻辑
3。将这个类在配置文件中进行注册
public ActionForward execute(ActionMapping mapping, ActionForm form, HTTPServletRequest request, HTTPServletResponse response) throws Exception{
//ActionForward:封装了跳转目标的路径
//mapping:访问配置文件
//form:传过来的ActionFrom对象
//跳转部分写法如下,变量可以保存在request里面,因为ActionForward默认的不是进行重定向跳转,而是进行forward跳转,所以不会丢失
ActionForward af = new ActionForward("/queryResult.jsp");
return af;
}
////////注册
运行流程总结:客户端JSP提交到ActionForm,ActionFrom根据客户端JSP里的action,去掉".do"后,获得/query --> 在xml中的mapping中查找到/query --> 取得name里的queryForm --> 将提交的内容送给queryForm --> 又根据mapping 中的type获得Action的地址,将ActionForm中打包的内容送给Action
///////可以将所要跳转的地址设置成为逻辑名称
在action中跳转代码则变成:ActionForward af = mapping.findForward("RESULT");
-------------------------------------3----------------------------------
//////////自己建立配置文件的映射关系只需要在config文件的图形界面中右击new->form action and jsp
Struts框架包括自定义标签库,它可以用在很多方面.尽管这些库并不要求用框架,但是使用他们会有助于程序的开发.
struts-html taglib : 包含用来生成动态html用户界面和窗体的tag
struts-bean taglib : 包含在访问bean和bean的属性时使用的tag,也包含一些消息显示的tag
struts-logic taglib : 包含的tag用来管理根据条件生成输出文件,和其他一些用来控制的信息
tld文件是标签库定义文件(tag library definition)
/////////////////html标签库
其中的
//需要在ActionForm中定义同名的property,并设置set,get函数.如果设置了value的话则不需要,因为:
在Struts标签中如果没有手动设置property的value值,则系统会自动调用ActionForm的getter函数获取初始值,不过最好还是定义一下
文本框:
密码框:
多行文本框:
隐藏表单:
单选按钮:
private String sex = "boy";
下拉菜单:
成组多选按钮://最好使用multibox
在ActionForm中需要定义一个数组来存储多选按钮的值:private String[] fav;//不能设置初值,有问题,要使用可以设置初值的则选用
设置初始值,private String[] fav = {"初始值1","初始值2"};
单个复选按钮:
ActionForm中定义如下:private boolean inteam = true;//但是此方法会出现inteam的值不可以更改,可在reset函数(每次提交都执行一次)
中设置如下:inteam = false;
多选下拉列表框:
ActionForm中定义如下:private String[] books = {"sanguo","hongloumeng"};//可以跳着多选,并不需要顺序对应
-------------------------------------4----------------------------------
html标签库:生成链接
1。
2。
3。
4。
链接的同时传递参数
1。
2。<% session.setAttribute("msg","1"); request.setAttribute("msg","2"); application.setAttribute("msg","3");%>
//系统自动从page--->request--->session--->application中寻找参数paramName 对应的参数
其他情况:在一个类中的属性作为参数
<% Student stu = new Student(); stu.setStuId("0001"); session.setAttribute("stu", stu);%>
其他情况:传递多个参数,可将多个参数放到HaspMap中
<% HashMap hm = new HashMap(); hm.put("param1","msg1"); hm.put("param2","msg2"); session.setAttribute("hm",hm);%>
/////////////////bean标签,访问http信息,name是从别处的来的,id是自己的
1。
2。
打印上面的内容:
3。
<% request.addCookie(new Cookie("username","cst"));%>
/////////////////logic标记,比较运算,相当于if语句
1。
2。
3。
4。
5。
6。
7。
8。
9。
eg1:简单集合(包括数组)的遍历
ArrayList list = new ArrayList(); list.add("三国"); list.add("水浒"); list.add("西游");session.setAttribute("list",list);
eg2:集合里面还有JavaBean的情况
ArrayList stus = new ArrayList();
Student stu1 = new Student(); stu1.setStuId("0001"); stus.add(stu1);
Student stu2 = new Student(); stu2.setStuId("0002"); stus.add(stu2);
Student stu3 = new Student(); stu3.setStuId("0003"); stus.add(stu3);
session.setAttribute("stus", stus);
eg3:JavaBean里面含有集合属性的情况,假设Student里有熟悉private ArrayList phones;
Student stu = new Student(); ArrayList phones = new ArrayList();
phones.add("1213123"); phones.add("23423423"); stu.setPhones(phones); session.setAttribute("stu",stu);
eg4:复杂集合,以HashMap为例
HashMap hm = new HashMap();
hm.put("param1","msg1"); hm.put("param2","msg2"); hm.put("param3","msg3"); sessiong.setAttribute("paramList",hm);
-------------------------------------5----------------------------------
实际案例中分析时,看有几个动作,理论上有几个动作就需要几个Action,然后根据动作判断是否需要ActionForm
产生随机数:Random rnd = new Random(); int rndNumber = rnd.nextInt();
通过request获得session:HttpSession session = request.getSession();
如果使用
注意,跳转时:
-------------------------------------6----------------------------------
可以维护一个自定义标签,例如多个页面中有一个共同的菜单需要维护的时候,可以为这个菜单定义一个自定义标签
/////////////标签简介:
标签格式:<前缀:标签名属性="属性值"/>
空标签,没有体,也没有属性
有体有属性标签:
/////////////如何开发空标签和空体标签
自定义标签的要素:
1。标签处理程序(一个java文件,已经被编译):使用不同的方法和对象来定义标签的行为,即认识某属性的不同值能做不同的事情
作用:包含类和方法的定义,定义标签的功能
对于空体标签,需要继承:javax.servlet.jsp.tagext.TagSupport
对于有体标签,需要继承:javax.servlet.jsp.tagext.BodyTagSupport
以上两类都需要实现接口:javax.servlet.jsp.tagext.Tag接口
所要重写的Tag接口中的方法如下:
doStartTag();一般的返回SKIP_BODY,让标签不要对体求值.初始化标签的一些内容,如连接数据库.有体标签则返回EV AL_BODY_TAG,对体求值
doEndTag();一般的返回EV Al_PAGE,让标签后的JSP继续执行.做一些善后工作,如关闭数据库.有体标签同样返回EV AL_PAGE,让后面的继续执行
release();释放这个标签对象
doAfterBody();完成标签体求值之后调用
doBeforeBody();开始标签体求值之前调用
对于标签里面的属性,类似于JavaBean里的属性,对他们设置get和set方法
最厉害的角色:pageContext保护成员,可以通过它获得JSP的内置对象,从而可以向页面输出一些内容.
2。标签库描述文件(TLD文件)(一个XML格式文件):包含客户标签的描述性列
表的XML文件,即识别不同的属性能做不同的事情
3。JSP文件(为了嵌入自定义标签):包含标签以及表示内容的HTML代码
<%@ taglib uri="stu" prefix="自定义的前缀" %>
-------------------------------------7----------------------------------
资源文件(需要制定编码为gb2312):在Struts中生成的.properties文件,用于定义一些在多个页面中使用的信息或者资源
资源文件格式:key=value形式.eg:info.input.account=please input account :
调用:
可以使用资源文件,传参数来显示
# 可以使用参数{0}, (4)
info.input=please input {0} :
调用:
资源文件中还可以使用标签:info.input=please input {0} :
可以自己建立一个新的资源文件,然后在配置文件中进行注册:
调用:
//////////////在资源文件中使用中文的话需要转码:native2ascii -encoding gb2312 源文件名,目标文件名
此命令在jdk的bin目录文件下eg:native2ascii -encoding gb2312 a.properties
b.properties
//////////////错误处理,两类错误:
1。前端错误,如输入为空,一般在ActionForm中实现
在ActionForm中实现:
////1.首先在配置文件中设置inputJSP,即在Acion标签中的input选项(当前端出现错误时所要跳转到的页面)中设置出错后所要到达的页面
////2.在ActionForm中的Validate方法(进行前端的错误验证)中做以下动作:定义ActionErrors;如果有错误,添加ActionMessage,并指定属性名称和资源文件key 值;返回ActionError(ActionErrors是错误集合,当内部有ActionError时则认定前端发生了错误)
eg:资源文件中定义错误:error.null={0} cannot be null
ActionForm中定义了:ActionMessage error = new ActionMessage("error.null","account");//第一个参数是资源文件中的key,后面的是参数,可以使用多个参数.errors.add("account(对此error加一个属性标记",error);
////3.在页面中写
2。业务逻辑错误,比如登陆不成功,一般在Action中实现
需要保存错误:this.saveErrors(request, errors);//推荐第二个参数是ActionMessages类型
return mapping.getInputForward();
-------------------------------------8----------------------------------
1。ActionForm高级应用之Scope(范围),在Action标签中定义:
当scope=request时,表示每次提交都会新生成一个ActionForm对象;而当scope=session时表示在一次会话中生成一个ActionForm对象,以后不再生成,而是在session中取得;当scope=session时一定要注意reset方法.(一般情况下表单的数据都是暂态的,所以放到request中
2。ActionForm高级应用之表单跨页:(scope需要设置成session)在选择建立Action时选择Type为forward(只进行跳转,同时能对内容进行打包,无use cases):
3。ActionForm高级应用之利用索引属性的ActionForm(如电话号码有多个,可以使用数组属性,也可以使用索引属性)优点是跳转回去后能够保存原来的值,缺点是事先必须知道表单元素的个数(此缺点可以通过改成集合的方式来克服掉)
ActionFrom中定义如下:
private String[] phones = new String[3];
public String getPhone(int i){
return phones[i];
}
public void setPhone(int i, String phone){//i和phone的顺序不能变,因为那是规
范
this.phones[i] = phone;
}
使用集合的方法:缺点是失去了顺序,慎用
private ArrayList phones = new ArrayList();
public String getPhone(int i){
if(i < phones.getSize()){
return (String)phones.get(i);
} else return null;
}
public void setPhone(int i, String phone){
this.phones[i].add(phone);
}
-------------------------------------9----------------------------------
4。ActionForm高级应用之动态ActionForm(因为过多的额ActionForm让系统过于庞大.)解决如下://但是此方法会使得失去验证功能
////建立动态的ActionForm
建立ActionForm类的时候在Form Impl中选择Dynamic FormBean,可以避免代码的编写,系统自动在配置文件中注册如下
////使用DynaActionForm.get()方法使用动态ActionForm
DynaActionForm regForm = (DynaActionForm)form;
String account = regForm.get("account");
String password = regFOrm.get("passowrd");
////////////////前端验证:
1。ActionForm验证
2。使用Validate框架验证(核心思想:将验证的作用写在XML文件中,使许多判断的if语句相对集中在XML中了)
使用:首先必须有两个jar文件:Jakarta-oro.jar处理文本文件和commons-validator.jar提供验证功能;其次需要系统提供的文件
validator-rules.xml(此文件定义了我们项目中可能出现的所有要验证的规则,它是Struts自己定义的,以后只要在自己的XML文件中调用即可)
此xml文件中定义如下:包含了一些通用规则,一般不需要改变
////////////////步骤:
1。首先建立validator-rules.xml文件和validation.xml文件(此文件是自己写的,
可以命名其他名字)
2。将这两个文件作为插件存入Struts配置文件,在Struts配置文件中最后加上:(因为这两个文件都是struts所不认识的)
3。编写JSP,ActionForm,Action,注意此时ActionForm应该继承org.apache.struts.validator.ValidatorForm(静态的ActionForm);如果是动态的ActionForm则需要继承org.apache.struts.validator.DynaValidatorForm,然后就可以在validation.xml文件中写验证规则了
动态ActionForm中的type属性需要改成org.apache.struts.validator.DynaValidatorForm
validation.xml文件编写如下:
////////////高级内容之设定单个验证门限:如电话长度最少7位,
方法:在field中定义
参数中可以使用所定义的var:
////////////设定多个验证门限:如果是对范围设定门限,则只要对min,max设定就可以了
////////////设定条件验证门限:在field中增加validatewhen,定义:
如果不适用框架,而是在ActionForm中做验证,而且是一些比较复杂的验证,推荐使用静态类https://www.doczj.com/doc/4d14966298.html,mons.validator.GenericValidator
-------------------------------------10----------------------------------
Po:持久化对象;Vo:值对象
??为何保存在session中的对象,在更新以后不需要再次将其添加到session中? -------------------------------------11----------------------------------
/////////////Action高级应用之DispatchAction(Action的子类,用于实现轻量级组件,可以在一个Action中实现多个操作),传统方法可以通过设置一个状态变量,通过状态变量不同的值来标示不同的操作.
实现步骤:(注意表单method=post)此方法可以降低耦合性,缺陷:JSP需要认识Action里的方法名,可以使用MappingDispatchAction解决
1。建立一个DispatchAction,并给定参数method,编写处理函数(可以继承DispatchAction来实现)
在配置文件中的action中需要添加parameter="自己给定名称,用来在调用action时指定用于处理的函数名称"
2。在JSP中使用action路径?method=方法名称的方式来提交
/////////////Action高级应用之MappingDispatchAction(降低耦合性,并且只编写一个Action而让他指向多个不同结构的ActionForm)
实现,需要在配置文件中写多个Action标签,其中的parameter需要改成所要调用的函数的名称
/////////////Action高级应用之LookupDispatchAction(处理一个表单具备两个不同的按钮,传统方法中可以对两个的按钮起不同的名字)
使用方法:(此方法降低了耦合性)
1。先建立ActionForm和相应的JSP,建立LookupDispatchAction,注意,按钮标签从资源文件中获得!
2。重写getKeyMethodMap函数,注意map.put(资源文件key,方法名);此方法即用一个map保存资源文件key和方法名的映射
Map map = new HashMap();
map.put("key1","函数名1");
map.put("key2","函数名2");
return map
3。编写方法
4。为Action建立参数
在配置文件中的action标签里添加parameter="名称随便",然后在提交按钮中需要设置:
5。将提交按钮property和参数名称一致
-------------------------------------12----------------------------------
一个页面中有多个栏位时,可以使用传统框架实现,也可以使用Tiles布局来实现1。传统方法:可以使用将页面共同部分做成小页面然后在整合页面中使用 page="a.jsp">
3。使用Struts的Tiles模板功能:
定义一个模板:layout,在需要不同的方写:
在页面中调用模板:
注意:整个页面是一个页面,不能进行局部跳转,如果非要实现在页面访问时先要访问数据库的话,可以先访问此Action,然后再让Action跳转到主页面中进行显示
-------------------------------------13----------------------------------
分页策略:1。内容全部查询出来以后再分页(查完再分).2。根据该页需要显示的内容进行分页(用多少查多少).选择:权衡查询难度和数据量
页数计算:if(总的条数%每页条数==0) 页数=总的条数/每页条数else 页数=总的条数/每页条数+1
第N页显示第几条记录(记录从0开始计算):(N-1)*每页条数=< 序号<= N*每页条数-1 或者(N-1)*每页条数=< 序号< N*每页条数
本质:传入一个比较大的集合,返回需要显示的页上记录
注意:如果一个参数是boolean类型的话,不要将其命名为isXXX,因为默认生成getter,setter函数的时候名称会有问题
遗留问题:为何存入request中的变量,在点击下一页,上一页后会消失掉,造成多次查询数据库~~~~!!
-------------------------------------14----------------------------------
文件上传:需要考虑的问题:文件编码,大小和分块.但在Struts中,一切都很容易,有一个upload包,专门负责这个工作
步骤:
1。如果表单中有文件要上传,表单的属性:
-enctype="multipart/form-data",这个属性告诉Struts,表单的数据将被编码并且具备多个部分(写在表单头中)
-
2。需要在ActionForm中定义一个同名属性,其类型是:org.apache.struts.upload.FormFile
此类有以下常用方法:getContentType(得到文件类型);getFileName(得到文件名称);getFileSize(得到文件大小)
如果不选择而提交,getFileName得到的是空字符串,getFileSize得到0.并且这个控件支持中文
////////////限制文件大小:在配置文件中设置
////////////保存文件在服务器端:(默认得是保存在bin目录下) FileOutputStream fos = null;//java.io.FileOutputStream
try{
byte[] data = file.getFileData();
String fileName = file.getFileName();
//有第二个参数,不写的话表示再次上传的时候进行覆盖,如果第二个参数写为:new FileOutputStream(fileName,"true").则在第二次上传的时//候进行添加,而不是进行覆盖
fos = new FileOutputStream(fileName);
fos.write(data);
}catch(Exception ex){ex.printStackTrace();}
finally{
try{fos.close();}
catch(Exception ex){ex.printStackTrace();}
}
/////////////更改文件上传路径:注意:java在访问服务器硬盘时,一定要提供逻辑路径(如c:\...),应用默认bin目录下
1。fos = new FileOutputStream("绝对路径" + fileName);//可以用,但一但服务器地址变了的话,更改起来比较麻烦
2。使用application
ServletContext application = this.getServlet().getServletContext();
String realPath = application.getRealPath("/FILES/");//其中FILES当前项目下的一个文件夹
fos = new FileOutputStream(realPath + "/" + fileName);
/////////////getInputStream()得到文件的输入流,返回InputStream.可以对文件进行分析
分析文件流:BufferReader br = new BufferReader(new InputStreamReader(is));//通过BufferReader来读取文件
/////////////上传多个文件:传统的数组方法已经不能使用了,建议使用ArrayList来保存
步骤:
1。将控件定义为索引(还不会!)
2。定义索引属性,可以用数组,也可以用ArrayList来存储
-------------------------------------15----------------------------------
//////////////多模块:对于庞大的系统,多个模块中的内容有相同部分,但却又细节不同,一个Struts-config.xml文件有缺陷,可以建立多个配置文件;另外如果是分工合作,在整合的时候可以使用一个模块将其他的模块进行整合,也用到了多模块: 1。建立单独的Struts配置文件
2。在W eb.xml中配置相应信息:
增加一个参数名称为config/模块名的参数,指明另一模块配置文件的路径.注意:模块名称和目录名称要一样
如果是通过链接调用的话
默认模块:
/////////另一种模块切换方法:在配置文件中配置如下:
调用:
//////////////插件开发:有些时候希望Struts在启动的时候做一些初始化工作:
1。传统方法:使用过滤器,系统启动自动调用init一次,以后每次提交调用doFilter 使用方法:
建立一个类,实现javax.servlet.Filter接口
在web.xml中进行注册:
2。Struts插件方法:(只实现服务器启动时初始化,并不实现每次调用时进行提交,比过滤器少了doFilter函数)
////建立一个类,实现org.apache.struts.action.PlugIn接口
////编写方法,注意servlet参数,用处很大
////注册插件
注意:在配置文件中可以通过设置属性来影响插件行为
3。另一种扩展:让表单在处理之前做一些事情:传统方法使用过滤器,但是并不能访问Struts对象(只接受表单提交,且通过this可以访问Struts资源)
一个隐藏在后面的角色:RequestProcessor类,Struts运行时,提交到ActionServlet,底层实际上是调用RequestProcessor来完成工作的
////建立一个类,继承:org.apache.struts.action.RequestProcessor
////编写方法,注意重写方法processPreprocess,注意返回值(一般返回true,表示继续向下传递,而false表示到此为止)
////配置控制器:
-------------------------------------16----------------------------------
Hibernate思想:用一个类专门负责组织SQL,表名和列名在配置文件中注册,将表名对应到Customer类,列名对应到Customer类的属性,让数据库对DAO来说是
透明的.需要两个配置文件,分别负责数据库的链接,负责对象和关系表的映射(ORM)-------(可以自动组织SQL语句)
///////持久化层,O/R Mapping
基于B/S的典型三层架构:
展现层(Presention Layer) --->业务逻辑层(Buseness Layer) --->持久化层(Data Source Layer)
W ebW ork/Struts --(IoC)-->Spring
--(IoC)-->Hibernate
Action,FormBean,配置文件,模板页面--->IoC容器,AOP,Hibernate的支持,事务管理--->映射文件,Hibernate接口,DAO模式
///////Bean一般表示数据表中的一条记录,只是对记录的操作可以转换为对对象的操作,操作之后数据库的记录相应变化,必须提供对这些对象操作的函数,Bean能够通过函数对数据库实现增删改查.
Hibernate使用:(不需要服务器,可以建立java项目来实现)
1。建立数据库记录封装类po.Customer
2。写另一个配置文件:Customer.hbm.xml;//hbm代表的是hibernate Mapping
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"https://www.doczj.com/doc/4d14966298.html,/hibernate-mapping-3.0.dtd">
3。在hibernate配置文件中对建立的配置文件进行注册
4。实现增删改查(另外需要写一个类)
//////////添加一条记录
-读取Hibernate配置文件:
Configuration conf = new Configuration().configure();
-Hibernate操作要由Session来完成,Session由SessionFactory来管理,所以要生成SessionFactory:
SessionFactory sf = conf.buildSessionFactory();
-打开Session(并非web里面的Session,而是Hibernate的Session,跟web里的Session完全不同):
Session session = sf.openSession();
-增删改查(注意Session的事务不是自动提交):
设置自动提交:Transaction tran = session.beginTransaction();
session.save(new Customer("1","1","1",1));//或者session.saveOrUpdate(new Customer("1","1","1",1));//有就更新,没有就添加
https://www.doczj.com/doc/4d14966298.html,mit();
///////////查询一条记录
Configuration conf = new Configuration().configure();
SessionFactory sf = conf.buildSessionFactory();
Session session = sf.openSession();
Customer cus = new Customer();
session.load(cus,"主键值");//多于一条记录时会抛出异常
///////////修改一条记录
Transaction tran = session.beginTransaction();
session.update(cus);
https://www.doczj.com/doc/4d14966298.html,mit();
///////////删除一条记录
Transaction tran = session.beginTransaction();
session.delete(cus);
https://www.doczj.com/doc/4d14966298.html,mit();
-------------------------------------17----------------------------------
///////////org.hibernate.cfg.Configuration:(注意:这是一个瞬态对象,一旦SessionFactory建立,就丢弃,占据系统资源较少)
作用:负责管理Hibernate的配置信息(hibernate.cfg.xml),hibernate映射文件(*.hbm.xml)生成SessionFactory
使用方法:读取xml文件(hibernate.cfg.xml)
Configuration conf = new Configuration();然后调用它的configure()函数,默认读取hibernate.cfg.xml
configure()方法可以指定参数;
addResource(String path)可以指定hbm文件路径;(即可以不在hibernate.cfg.xml 中注册其他的配置文件,而是动态添加配置)
addClass(Class persistentClass)只指定类;
///////////org.hibernate.SessionFactory:
应用程序从SessionFactory中获得Session实例,通常情况下一个数据库只用一个SessionFactory,例如应用初始化时建立(消耗内存),网站中适合放在application 中
///////////org.hibernate.Session:(代表与数据库的一次操作)
Session通过SessionFactory打开,在完成操作之后,需要关闭;它与web中的HttpSession没有任何关系.(网站时适合保存在HttpSession中)
如何生存Session是一个麻烦问题,可以借助帮助类来进行优化(HibernateSessionFactory(名字不定非要这样)),则生成session的代码就变为: Session session = util.HibernateSessionFactory.getSession();//该类有方法getSession和closeSession
util.HibernateSessionFactory.closeSession();//关闭Session
///////////比较好的事务操作方法:(使用错误处理的方法)
try{
session.update(cus);
https://www.doczj.com/doc/4d14966298.html,mit();
} catch (Exception ex){ tran.rollBack();//回退}
finally{util.HibernateSessionFactory.closeSession();}
///////////简单增删改查:
增加:save(单纯的添加),saveOrUpdate(如果存在就更新,不存在就添加)
查询:load(找不到时抛出异常),Customer cus = (Customer)session.get(Customer.class,"主键值");//找不到时返回空,不抛出异常(常用)
///////////复杂增删改查:(批量查询之:HQL(Hibernate Query Language)
基本语法:
1。from 类名as 对象名(where 属性条件);
eg:from Customer where cbalance>1000;//或者from Customer as cus where cus.cbalance>1000(注意:用的是类的属性,而不是数据库表)
String hql = "from Customer where cbalance > 1000";
Query query = session.createQuery(hql);
List list = query.List();//查询,并返回一个list
for(int i = 0; i < list.size(); i++){//遍历
Customer cus = (Customer)list.get(i);
}
2。select 内容from 类名as 对象名(where 属性条件)
eg:select cname,cbalance from Customer where cbalance > 1000;//只查询姓名和余额
String hqp = "select cname,cbalance from Customer where cbalance > 1000"; Query query = session.createQuery(hql);
List list= query.list();
for(int i = 0; i < list.size(); i++){
Object[] obj = (Object[])list.get(i);//此时list里放置的不是对象,而是object 数组
}
3。使用参数":参数名"
double money = 1000.0;
String hql = "from Customer where cbalance > :money";
Query query = session.createQuery(hql);
query.setDouble("money",money);
///////////复杂增删改查:(批量查询之准则查询方法:org.hibernate.Criteria)
步骤:
1。Criteria cri = session.createCriteria(Class persistentClass),将Criteria绑定到JavaBean
2。Criteria.add(规则); Criteria.addOrder();//eg:cri.add(Restrictions.gt("cbalance",1000));//增加限制:cbalance>1000
3。规则由Restrictions类得到
4。用list方法得到结果
注意:这种方法也支持聚合,连接等操作,但使用得较少.可以进行排序:cri.addOrder(Order.asc("所要排序的列"));
注意Criteria的两个重要方法:
c.setFirstResult(i);//从第i条记录开始显示
c.setMaxResults(i);//最大显示的记录号
给分页带来了方便
///////////复杂增删改查:(批量查询之:SQL查询)(不太常用的方法)
步骤:
1。SQLQuery sq = session.createSQLQuery(String sql);
2。用SQLQuery.addEntity(Class class)方法来绑定对象
3。用list方法得到结果
注意:在使用查询的时候,如果遇到查询的结果无法放置到JavaBean中
注意:在实际项目实施当中,对数据库比较批量的操作应该写成存储过程
//调用存储过程:Session通过Connection绕道JDBC
java.sql.Connection conn = session.Connection();
conn.prepareCall(s);
-------------------------------------18----------------------------------
在IDE中导入数据库的驱动:在MyEclipse中的Hibernate窗口中建立一个数据库连接模板就可以了(注意JdbcOdbcDriver在rc.jar包中,不可见)
//////////复合主键的情况
1。编写一个类(实现序列化接口),封装主键,并写属性,原类则去掉主键属性,增加新建立的类属性,增加get,set函数
2。po内编写各个属性,包括主键类型
3。在映射文件中写明:
//////////主键生成策略:Generator:主键生成器,每个主键都必须定义相应的主键生成策略,它用来为持久化类实例生成唯一的标志.
Hibernate内置主键生成策略:
assigned:由用户手工给定一个值(例如账号由用户决定)
increment:不用手工给值,由系统自动递增(注意,这些只是Hibernate的策略)账号由系统返回.需要保证列是数字,而非字符串
identity:由数据库生成主键
sequence:由数据库根据序列生成主键
hilo:根据hibernate特殊算法生成主键
native:系统自动选择identity,sequence,hilo
uuid.hex:hibernate利用uuid算法生成主键
//////////动态模型:不用编写po
更改配置文件:
在类中使用动态模型:
HashMap hm = new HashMap();
hm.put("account", account);
hm.put("password", password);
hm.put("cname", cname);
hm.put("cbalance", cbalance);
Transaction tran = session.beginTransaction();
session.save("Customer", hm);
https://www.doczj.com/doc/4d14966298.html,mit();
-------------------------------------19----------------------------------
Hibernate处理表间关联的情况:(注意表间关联时可能会出现查询出错的情况,需要更换驱动jdts,SQL Server 打补丁SP4)
1。1对1关联:(两个类在配置文件中的主键要相同)Hibernate与数据库的耦合性很低,此处的主键设置与真实的数据库主键并无关系
要在没有外码的类(主动类)中,建立一个外码po类(被动方)的对象.(看例子)
再在主动类中的配置文件中进行注册:
2。1对多关联:one-to-many
要在没有外码的类(主动类)中,建立Set类型属性,用于装入所有与之关联的外码po类(被动方)的对象
再在主动类中的配置文件中进行注册:
添加的时候使用HashSet来存储set数据,然后进行添加操作
所存在的问题:
////////当表中定义了主键外键关系的时候存在bug,必须还要配置多对一,配置多对一关联如下:
-在Student类(外码类,被动类)中添加BanJi(主动类)属性
-在Student.hbm.xml中添加注册
-在BanJi.hbm.xml中set标签内添加属性:inverse="true"(表示它是主动方)
3。多对多关联:many-to-many(最多的操作时查询,因为增删改的时候问题比较多)
在主动类和被动类中都必须添加set属性
两个hbm文件中配置如下:
-------------------------------------20----------------------------------
使用Struts+Hibernate编程的时候,前台交给Struts处理,后台则交给Hibernate 处理(只需要添加配置文件,更改DAO代码即可,使得系统更加灵活,更具有低耦合性特点,而且降低了后台DAO开发人员的工作量)
面向接口编程的思想:对于Struts中的Action,不需要知道后台DAO的变动,可以为后台DAO创建一个统一的接口,让DAO实现这个接口,那么就可以达到DAO 内函数统一的目的.同时在Action中使用DAO的时候,使用: DAO接口name = new DAO();//接口类对象指向子类DAO对象
进一步改进:DAO接口name = 工厂类.getDAO();
需要建立一个工厂类,用于返回一个DAO接口类型指针,但其实返回的是一个DAO对象,这样就可以达到Action完全不依赖后台DAO的情况.降低了系统的耦合性.
BO:Business Object业务对象,比较注重业务逻辑,将某个实体能够做到的动作集中到一起,位于Action和DAO之间
-------------------------------------21----------------------------------
控制反转和依赖注入是Spring的两个核心思想!
使用工厂的时候可以运用反射机制:
public class BeanFactory{//框架化,这就是最早的String结构,可以处理多个相同结构的切换
public static Object getBeanDao(String aName){//aName是Action中传来的别名
String className = 根据别名到类名;
return Class.forName(className).newInstance();
}
}
Action中调用
ICustomerDao dao = (ICustomerDao)getBeanDao(别名);
////////在Spring配置文件中注册别名