学习笔记

*Javaweb*

Servlet就是运行在服务器的java类
动态页面:有交互的
servlet容器为Javaweb提供运行环境,也叫JavaWeb应用容器,典型的:tomcat
配置path其实是为了在任意目录都能启动
Cmd中打catalina可得若干选项
Run:本窗口启动,start:新窗口启动 stop:关闭

要在localhost界面manage,需要在conf文件下的uers.xml中加上

(用户名密码自己设置新版本不可为空,roles是什么要根据没设置时进入manage出错时的提示填写,8.5版本是manager-gui)

Web目录规范

(8989应为自己的tomcat端口)
优化:在第四步,对项目buildPath,选source修改默认输出目录为webcontent-web-inf-classes。
第六步:在tomcat/conf下新建目录catalina/localhost然后在里面新建helloworld2.xml,

则访问localhost:8989/helloworld2/hello.jsp可访问hello.jsp。(path没怎么起作用可删除,主要是后面俩,docBase是原文件的物理路径(jsp就在这路径下) reloadable:当修改了docBase下的classes目录下的class文件时,tomcat会重新加载web应用。

虽然实用性并不强,但是有助于理解web项目架构与tomcat属性

Servlet

在web.xml的servlet映射中,配置一个普通类,其中包含一个static块和一个main方法,在浏览器运行后,static块能运行,但是紧接着报错:该类不能映射为servlet类,另一方面,在映射中,同一个class可以被多个mapping映射,即一个文件可以用多个url访问到

Servlet容器管理servlet整个生命周期,即servlet类可以被容器(tomcat)创建销毁,而不需要手动new等,另一方面,类似JSP,Filter,Listener,Tag等也是被容器掌握

Servlet有四个与生命周期相关的方法:构造器(只有第一次请求时,才会创建实例,说明servlet时单例的,所以不建议在其中写全局变量,可能造成线程安全问题),init(创建实例后立即被调用,用于初始化),service(被多次调用时,每次请求都会调用,包括第一次),destory(当前servlet所在的web应用被卸载前调用)

在映射的servlet-class后可以接一个load-on-startup选项,使服务器启动时servlet启动,(有多个servlet时)其中的数字越小,越先启动,最小为0.为负数不起作用。

注意1.servlet存储目录要放在\WEB_INF\classes中(靠设置输出路径,\build\classes也可以)
2.mapping中可以用通配符* 斜杠表示 表示任意 有两种使用方法:1/ 2*.扩展名(如*。html),有扩展名不能打斜杠

ServletConfig 封装了Servlet的配置信息,并且可以获取ServletContext 对象
配置servlet初始化参数,是在web.xml中的servlet中,用init-param(含param-name和param-value)配置,必须放在load-on-startup之前,可以有多个
获取初始化参数方法:法1.用servletConfig .getInitParameter(String name)
法2 servletConfig .getInitParameterNames()得到的是init-name组成的Enumeration 用.nextElement()返回String形式(用.hasMoreElement()遍历)
注意,此处的servletConfig是init方法中传入的ServletConfig 类参数。这也是init相对构造器的重要区别

servletContext 可以由servletConfig获取(getServletContext()),该对象代表当前Web应用,可以从中获取到当前WEB应用的各方面信息,
1.用getInitParameterNames()等方法获取WEB应用的初始化参数(独立于任何一个Servlet的,是全局的,可以被所有的Servlet所获取使用)
ps:web的初始化参数用配置
2.获取web应用中某一文件在服务器上的的绝对路径:getRealPath(String path) (path为相对路径,作用域为WebContent)
3.获取当前应用的名称(即”/项目名称”)getContextPath()
4.获取当前WEB应用的某一个文件的输入流getResourceAsStream(String path):path 的/为dangqianWeb应用根目录(结果类型为InputStream)
5.其他,如Attribute相关的等
注意:只有在init中用servletConfig处理过servletContext,才能在service中用request.getServletContext()获取到,不然是空,另外,servlet直接getContext是要servlet3.0以上才行,不然要先getsession
Get请求:地址栏输入ur,点超链接,表单选get方式
Request与Response
Servlet的service()方法用于应答请求
表单中的action可以和web,xml配置servlet中的url-pattern对应,从而达到提交表单时访问到某个servlet
放在WebContent文件夹根目录下的html文件是可以直接通过/文件名在网页访问到的,不需要映射
ServletRequest:封装了请求信息,可以从中获取到任何的请求信息
ServletResponse:封装了相应信息,如果想给用户什么响应,具体可以使用该接口的方法实现。
这两个接口的实现类都是服务器给予实现的,并在服务器调用service方法时传入

方法:
ServletRequest:

获取请求参数 String getParameter(String name):根据请求参数名返回参数值
Map getParameterMap():返回请求参数的键值对 key:参数名(String型) value:参数值(是String数组类型)
Enumeration getParameterNames():返回参数名对应的enumeration对象,类似于ServletConfig和ServletContext的getInitParameterNames()方法
String[] getParameterValues(String name):根据请求参数名,返回参数对应的字符串数组(用于像checkbox一类一个名多个值的,如果此时用getParameter(String name)只能获得第一个提交的值)

在获取请求url/uri,获取请求方式,获取请求字符串,获取servlet名字
如果一开始实现的servlet接口,则如果要使用getRequestURI等方法需要把servletrequest强转为httprservleteRquest(此处强转的原理是,在tomcat中request本身生成时是http类型的,但是向上转型为servlet类型了,所以可以向下转),但还有一个办法,就是一开始就用继承HttpServlet,service处也入参HttpServletRequest就好了。此处要注意,如果一开始就用的HttpServlet,name默认的service会把Post和get分别发给doPost与doGet方法处理,应该重写这俩方法,但是如果重写了service,则这两个方法失效,用service统一处理

ServletResponse:封装相应信息,如果想给用户什么响应,可以使用该接口的方法实现

getWrite():返回PrintWriterr对象,调用Print()方法,将信息打印到用户浏览器上(不是控制台)
可以用setContentType()设置响应内容的类型,比如在上一个方法前使用response.setContentType(“application/msword”);则信息不打印到屏幕上,而是会让浏览器下载一个word文档,打印的内容放在文档内
对于HttpServletResponse sendRedirect(String Location):请求重定向

GenericServlet

需要注意的是,他的不带参的init()并不由服务器掌握。要重写init()可以在这个不带参的里面写,或者在带参里面写,但是第一行写super.init(config) .

HttpServlet
是一个Servlet,继承自GenericServlet,针对Http协议定制。他在service方法中把request,Response中强转为http的,并调用重载的service,然后在重载的service中获取请求方式,根据请求方式调用自建的doXXX(主要是doPost和doGet)方法。实际开发中复写doXXX方法即可

JSP

Jsp是Java和html混写的文件,本质上是一个servlet。
静态内容用html,动态内容用java。放在web应用中除了web-inf及其子目录外的其他目录中。

Jsp页面有几个隐藏变量(在原生方法中定义了,不需要手动声明添加):
Request:是HttpServletRequest对象
Response:是HTTPServletResponse对象在jsp页面中几乎不会用
pageContext,是pageContext的对象,可以获取当前页面的所有信息
session,:是HttpSession的对象代表浏览器和服务器的一次会话
application:代表当前web应用,是ServletContext对象
config,是当前jsp对应的servlet的ServletConfig对象,几乎不用。若需要访问当前JSP配置的初始化参数,需要通过映射的地址才可以换成
out,是JSspWriter对象,用out.println()可以打印到浏览器上,要换 行需要在两者中加
或打印
page 不用!指向当前jsp对应的servlet对象的引用,但为object类型,只能调用object类的方法
exception 在声明了page指令的isErrorPage=“true”时才可以使用

pageContext,request,seesion,application(对属性的作用域从小到大)

小技巧:一
可以将java与html混写,并通过java逻辑判断是否输出,如:
<%
String agestr=request.getParameter(“age”);
if(agestr!=null){
Integer age=Integer.parseInt(agestr);
if(age!=null&&age>18){
%>
成年人
<%}else{
%>
未成年
<%} }%>
这说明多个脚本代码片段可以相互访问
二,可以直接用<%= a %>把变量输出,等同于out.print(a)

三,不能直接在jsp中声明方法,因为<%%>中写的东西在service方法中,方法中不能声明方法
但是<%! %>之中的将被插入service方法外面,但是在jsp中很少使用

四,<!– –> 是html注释,<%– –%>是jsp注释,html注释无法阻止java代码的执行

与属性相关的方法
Void setAttribute(String name,Object o)
Object getAttribute(String name);获取指定属性
Enumeration getAttributeNames()
removeAttribute(String name):移除指定属性

pageContext request session application 对象都有这些方法
这四个对象称为域对象
pageContext:属性作用范围限于当前jsp页面(在servlet类中无法获得)
request:属性的作用范围仅限于同一个请求
session:属性作用范围限于一次会话(一次会话指浏览器打开直到关闭且会话不失效(比如挂机太久))
application:属性作用范围限于当前应用(全局)

注意:在eclipse新建2.5版本以上的servlet时,不会配置web.xml,而是改用注释的方式配置,如@WebServlet(“/forwardServlet”)

请求转发与重定向

转发方式:
String path=”testServlet”;
RequestDispatcher requestDispatcher=request.getRequestDispatcher(“/”+path);(去掉了斜杠好像也可以)
requestDispatcher.forward(request, response);

或者request.getRequestDispatcher(“c.jsp”).forward(request, response);

重定向:
String path=”testServlet”;
response.sendRedirect(path);
或者
response.sendRedirect(“c.jsp”)
本质区别:请求的转发只发出了一次请求(就是浏览器和Web容器只有一次交互,转发工作由Web容器自己完成),而重定向则发出了两次请求(第一次返回的response中浏览器发现有重定向信息,于是再次向Web容器发送请求)。
转发:1.地址栏是初次发出请求的地址
2.在最终的Servlet中,Request对象和中转的那个request是同一个对象
3.只能转发给当前WEB应用的资源
4./代表当前web应用的根目录(比如http://localhost:8080/WebApp/

重定向:1.地址栏不再是初次发出的请求地址,而是最后相应的地址
2.在最终的Servlet中,Request对象和中转的那个request不是同一个对象
3.能重定向到任何资源
4./代表当前web站点的根目录(比如http://localhost:8080/)

JspPage

Import导包用
Session取值为true或false,指定session隐藏变量是否可用(即访问当前页面时是否一定要生成HttpSession对象)”
errorPage=”/a.jsp”:页面出错时跳转至a.jsp(用的转发)
isErrorPage=”true” 用在错误页面,这样该页面就可以用exception隐藏对象来获取错误信息。但是写了exception后不能直接访问该页面,因为exception是null会报错

对于Tomcat服务器而言,WEB-INF文件夹下的文件不能通过浏览器直接输入地址访问,可以通过请求转发访问
所以errorPage可以放在WEB-Inf下。
此外,还可以在web.xml中配置错误页面(在错误为或错误类型为时跳转至)
contentType:指定当前Jsp页面的响应类型,实际调用的是response.setContentType(“text/html;charset=UTF-8”),如果把text/html换成application/msword,则访问时返回一个doc文件。所以通常情况下都用text/html. Charset指定返回的页面的字符编码

pageEncoding:指定当前Jsp页面的字符编码,通常与charset一致
isELIgnored 指定当前Jsp是否忽略el表达式,通常为false

Jspinclue

正文中<%@ inclue file=”相对路径”%>静态地引入另一个界面(最后只会生成一个(servlet)java文件),这种源码级别的引入导致可以在一个文件里声明一个变量,然后在另一个文件里输出这个变量。

举个例子:a.jsp中声明一个Sting str,然后引入b.jsp 在b.jsp中直接输出str,则b.jsp会报错,因为b没有这个变量。但是访问a的话,能正常显示str内容(因为对于a而言,已经把b的源码合并过来了,所以是一个正常的声明然后输出的过程)。当然,如果这种情况是从b引入a,则不会报错,因为把a的源码拿过来了

Jspinclude标签
用法中间可以加子标签,这是动态引入,会生成两个class文件,只是在其中一个文件中有一个指令引入另一个,于是乎不能一个文件声明一个文件使用

Jspforward标签
中间可以加子标签等同于dispatche那个forward

以上两个标签都可以使用jsp:param子标签传参数,被传参的可以用request.getParameter()提取

解决乱码
1. 在jspPage中保证两处设置都为UTF-8,浏览器编码设置正确
2. 为了保证传参的中文正确显示(如form中的中文):
对于Post请求,在使用参数之前设置request.setCharacterEncoding(“UTF-8”)
对于Get请求:上述方法失效。鉴于参数传递过程中默认的编码方式为iso-8859-1,那么可以在使用时先解码后编码。

举例:String val=request.getParameter(“username”);
String username=new String(val.getBytes(“iso-8859-1),”UTF-8”);
但是每次都这么处理很麻烦,所以如果要使post的方法对于get同样起作用,需要修改tomcat:
在tomcat-conf-server.xml中找到
这行,在末尾添加变为

同时要保证映射的(就eclipse里那个server里找)server.xml也要修改

MVC

Pojo 与数据库这部分叫Model,表示业务数据与业务逻辑。一个模型能为多个视图提供数据
JSP与JSTL这部分叫VIEW(视图),向用户显示数据,接收用户输入,但不具体处理
Servlet为控制器(Controller)

根据MVC写增删改查
Tips:

AJAX

1.不刷新页面可以跟服务器进行通信的方式,主要方式是使用XMLHttpRequest对象
2而使用XMLHttpResponse对象实现Ajax只用了解,因为实际上主要用jquery或者封装好的方法
3.Ajax传输数据的三种方式:
Xml:笨拙,不易解析但是通用数据交换格式
Html:不需要解析,传输数据有限若只更新一部分区域可以使用。代码需要拼装完成。
JSON:小巧,有面向对象的特征,且有很多第三方jar包可以把java对象或集合转为json字符串。
3.使用jQuery完成Ajax:
Load方法,可以用于HTML文档的元素节点,把结果直接加为对应节点的子元素。通常而言,load方法加载后的数据是一个HTMl片段。使用方法:
Var obj=Varurl=Varargs=key:val,; o b j = … V a r u r l = … V a r a r g s = k e y : v a l , … ; obj.load(url,args);

.get, . g e t , .post, getJSON:使load//urlAjaxURL//argsJSON//dataAjaxXMLHTMLJSON g e t J S O N : 更 加 灵 活 , 除 去 使 用 l o a d 方 法 的 情 况 , 大 部 分 情 况 都 用 这 仨 。 / / u r l : A j a x 请 求 的 目 标 U R L / / a r g s : 传 递 的 参 数 , 是 J S O N 类 型 / / d a t a : A j a x 相 映 成 功 后 的 数 据 , 可 能 是 X M L , H T M L , J S O N .get(url,args,function(data){

})

请求JSON数据

法一 .get(url,args,function(data),JSON); . g e t ( u r l , a r g s , f u n c t i o n ( d a t a ) , ” J S O N ” ) ; 法 二 .post(url,args,function(data){
},”JSON”);
法三$.getJSON(url,args,function(data){
});

Eval可以把本子字符串转为JS代码执行
Var jsonStr=”{‘name’:’zsa’}”
Var testObject=eval(“(“+jsonStr+”)”);
Alert(testObject.name)

用jquery可以大大缩短代码,可以用load get和post

如果用getJSON,返回的data直接就是json对象,可以直接用data.person.name这种方式获得参数

反射

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

同一个类的Class对象是唯一的,不管生成几次都是同一个
获取class对象有三种方法
1tudent stu1 = new Student();//这一new 产生一个Student对象,一个Class对象。
Class stuClass = stu1.getClass();//获取Class对象

2Class stuClass2 = Student.class;//需要导包

  1. try {
    Class stuClass3 = Class.forName(“fanshe.Student”);//注意此字符串必须是真实路径,就是带包名的类路径,包名.类名
    } catch (ClassNotFoundException e) {
    e.printStackTrace();
    }

方法三最常用,而如果想在有class对象的基础上产生原有的类。则用Class stuclass=Class.forName(“包名.类名”);
stuclass. newInstance();//只能用无参构造器

使用newInstance()方法有两个条件:
1. 这个类已经加载;
2、这个类已经连接了。这两个条件都可以由forName完成(相当于对new()做了拆分)

在得到了一个类的Class对象后,可以从而获得该类的所有信息,比如构造器,方法,变量,父类,甚至是注释等等。以构造器为例:
Class clazz = Class.forName(“fanshe.Student”);
Constructor[] conArray = clazz.getConstructors();//获得所有公有构造方法
conArray = clazz.getDeclaredConstructors();//获得所有构造方法
Constructor con2 = clazz.getConstructor(null);//获得公有无参构造方法
con = clazz.getDeclaredConstructor(char.class);//获得以char为输入参数的构造方法
con.setAccessible(true);//可以忽略修饰符进行访问
Struts2
配置环境:导jar包(比较常用的可以在blank文件夹下找到),在web.xml中配置一个filter(在struts的blank下找到web.xml然后cv),最后在src中加一个struts.xml(可以在blank-web-inf-classes下找到然后cv)
不需要显式定义filter,而是使用struts2配置文件
Struts2中用package来组织模块,其中name是用来让别人继承的,而extends是用来继承别人的,通常继承struts-default(这个在struts-default.xml中定义),还有一个可以用的叫namespace,默认情况下为“/”,但是如果不为/后,每次调用action都得在前面加上这个(比如设为“/java”,name原来是localhost:8080/test/save.action就要变为localhost:8080/test/java/save.action才能正常访问)

一个struts2请求就是一个action
配置1
结果路径

配置2(此处为反射,调用class类的method方法,最后返回一个String与下面对应)

例子:

在index.jsp中

<form action="lll" method="post">
<input type="text" name="name2">
<input type="submit" value="提交">
</form>

在struts.xml中:

<action name="lll" class="struts2.TestClass" method="TestStruts2">
            <result name="success">/WEB-INF/success.jsp</result>
            <result name="fail">/WEB-INF/fail.jsp</result>
        </action>

在struts2.TestClass类中
public String name2;
public void getName(String name){//与属性名对应情况下方法名不重要,但是如果与属性名不对应,方法名就得设为“set属性名”,见后一个例子

        this.name2=name;
    }
    public String TestStruts2(){
        if(name2!=null&&name2.equals("fail")){
            return "fail";
        }
        return "success";
    }

Success.jsp中

Success

${name2}


而像TestClass这种能够出里Struts2请求的类称为Action 类

Action类中属性的名字必须遵守与JavaBeans属性名相同的命名规则,属性类型任意(从字符串到基本数据类型的数据转换可以自动完成)。 就是说Action类中的属性要与传来的参数名对应,比如上面例子中的“name” 。如果还有属性id的话,设为String类还是int类都无所谓。
另外其实还有一种,就是Action类的方法名设为set属性名,比如request中传来的参数为aaa,那么Action类设置一个setAaa方法也可以对应产生效果(此时就与传参名无关,即setAaa(String bbb){this.bbb=bbb}也可以起效果)

例子:

Index.jsp中

<form action="lll" method="post">
<input type="text" name="name2">
<input type="submit" value="提交">
</form>

Struts。Xml中

<action name="lll" class="struts2.TestClass" method="TestStruts2">
            <result name="success">/WEB-INF/success.jsp</result>
            <result name="fail">/WEB-INF/fail.jsp</result>
        </action>

TestClass中

public String name;
    public void setName2(String name){
        this.name=name;
    }
    public String TestStruts2(){
        if(name!=null&&name.equals("fail")){
            return "fail";
        }
        return "success";
    }

success.jsp中

<h4>Success</h4>

${name} 注意,此处是name不是name2,因为在testclass中赋予的是name

Action类必须有一个不带参的构造器(因为使用反射创建实例)
同一个Action类可以供多个action使用
Struts2会为每个HTTP请求创建一个新的Action实例,即Action不是单例的

在Action访问Web资源
I. 和 Servlet API 解耦的方式: 只能访问有限的 Servlet API 对象, 且只能访问其有限的方法(读取请求参数, 读写域对象的属性, 使 session 失效…).

> 使用 ActionContext:使用这个上下文获得MAP,操作map从而获取或添加修改

对于application和session用context.getapplication ()这种方式,对于request用(Map

  <result name="index" type="redirectAction">
        <param name="actionName">testAction</param>
        <param name="namespace">/atguigu</param>
    </result>
OR
<result name="index" type="redirect">/atguigu/testAction.do</result>

(需要新建一个package,namespace为对应的)

chain: 转发到一个 Action
注意: 不能通过 type=dispatcher 的方式转发到一个 Action

     只能是:
 <result name="test" type="chain">
        <param name="actionName">testAction</param>
        <param name="namespace">/atguigu</param>
    </result>
不能是:
<result name="test">/atguigu/testAction.do</result>

(ps:在struts.xml中配置接收的扩展名

通配符匹配

通常来说一般只会用一个通配符,比如,意思是action的name是succes杠什么,我们就用TestClass的什么方法。如果是有-这种,name第一个星用{1},第二个用{2}

动态方法调用:
忽略配置文件的方法,用自己的想用的方法,例子:
/strutsapp/Product!save.action 在扩展名前,context后加叹号,加方法名,调用Produce的save()方法。实际使用中,可以在提交action的时候就这么写
要使用这个方法需要激活动态方法调用:在struts2-core.jar static包 default-properties文件中找到dynamicMethod那一行,cv到struts.xml文件中,放后的开头位置

Ognl
helloWorld 时, ${productName} 读取 productName 值, 实际上该属性并不在 request 等域对象中, 而是从值栈中获取的.
ValueStack:
I. 可以从 ActionContext 中获取值栈对象
II. 值栈分为两个逻辑部分

Map 栈: 实际上是 OgnlContext 类型, 是个 Map, 也是对 ActionContext 的一个引用. 里边保存着各种 Map:
requestMap, sessionMap, applicationMap, parametersMap, attr
对象栈: 实际上是 CompoundRoot 类型, 是一个使用 ArrayList 定义的栈. 里边保存各种和当前 Action 实例相关的对象.
是一个数据结构意义的栈.

  1. Struts2 利用 s:property 标签和 OGNL 表达式来读取值栈中的属性值
    1). 值栈中的属性值:

    对于对象栈: 对象栈中某一个对象的属性值

    Map 栈: request, session, application 的一个属性值 或 一个请求参数的值.

    2). 读取对象栈中对象的属性:

    若想访问 Object Stack 里的某个对象的属性. 可以使用以下几种形式之一:

    object.propertyName ; object[‘propertyName’] ; object[“propertyName”]

    ObjectStack 里的对象可以通过一个从零开始的下标来引用. ObjectStack 里的栈顶对象可以用 [0] 来引用,
    它下面的那个对象可以用 [1] 引用.
    [0].message
    [n] 的含义是从第 n 个开始搜索, 而不是只搜索第 n 个对象
    若从栈顶对象开始搜索, 则可以省略下标部分: message

    结合 s:property 标签:

    3). 默认情况下, Action 对象会被 Struts2 自动的放到值栈的栈顶.
    但是如果自己push压入了栈,就不是了

Hibernate

hibernate所有操作都应该在事务管理下,即
Transaction tx=session.beginTransaction();与
tx.commit()之间

junit可以用@Before与@After @Test标注运行顺序
session

session的flush会检查缓存是否与数据库一致,若不一致则使刷入数据库(使用SQL语句更新数据库),不过有可能失败,因为有事务管理着数据库
执行HQL或者QBC查询时会先flush已得到数据表最新记录(虽然此操作不提交事务,也就是不会立即更新数据库,但是可以获得最新记录)
若ID是数据库自增的,则调用save()后立即发送INSERT语句,因为需要保证对象ID存在
而调用commit时,会先flush后提交事务

refresh():强制发送SELECT语句,使色三四年缓存中对象的状态和数据表中对应的记录保持一致。但是mysql的默认隔离级别为可重复读

ReadCommitted:只读已提交的数据,遇到未提交的事务型数据时,则一直等待。

ReadUnCommitted:可以读未提交的数据。
Repeatable read(可重复读取)读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务。
Serializable(序列化):提供严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行。

  1. save() 方法
    • 1). 使一个临时对象变为持久化对象
    • 2). 为对象分配 ID.
    • 3). 在 flush 缓存时会发送一条 INSERT 语句.
    • 4). 在 save 方法之前的 id 是无效的
    • 5). 持久化对象的 ID 是不能被修改的!

persist(): 也会执行 INSERT 操作
*
* 和 save() 的区别 :
* 在调用 persist 方法之前, 若对象已经有 id 了, 则不会执行 INSERT, 而抛出异常

get VS load:
*
* 1. 执行 get 方法: 会立即加载对象.
* 执行 load 方法, 若不适用该对象, 则不会立即执行查询操作, 而返回一个代理对象
*
* get 是 立即检索, load 是延迟检索.
*
* 2. load 方法可能会抛出 LazyInitializationException 异常: 在需要初始化
* 代理对象之前已经关闭了 Session

update:
* 1. 若更新一个持久化对象, 不需要显示的调用 update 方法. 因为在调用 Transaction
* 的 commit() 方法时, 会先执行 session 的 flush 方法.
* 2. 更新一个游离对象, 需要显式的调用 session 的 update 方法. 可以把一个游离对象
* 变为持久化对象
*
* 需要注意的:
* 1. 无论要更新的游离对象和数据表的记录是否一致, 都会发送 UPDATE 语句.
* 如何能让 updat 方法不再盲目的出发 update 语句呢 ? 在 .hbm.xml 文件的 class 节点设置
* select-before-update=true (默认为 false). 但通常不需要设置该属性.
*
* 2. 若数据表中没有对应的记录, 但还调用了 update 方法, 会抛出异常
*
* 3. 当 update() 方法关联一个游离对象时,
* 如果在 Session 的缓存中已经存在相同 OID 的持久化对象, 会抛出异常. 因为在 Session 缓存中
* 不能有两个 OID 相同的对象!
*
* 3. 若数据表中没有对应的记录, Session 也没有被关闭.
* get 返回 null
* load 若不使用该对象的任何属性, 没问题; 若需要初始化了, 抛出异常.

saveorupdate
1. 若 OID 不为 null, 但数据表中还没有和其对应的记录. 会抛出一个异常.
* 2. 了解: OID 值等于 id 的 unsaved-value 属性值的对象, 也被认为是一个游离对象
delete:
执行删除操作. 只要 OID 和数据表中一条记录对应, 就会准备执行 delete 操作
* 若 OID 在数据表中没有对应的记录, 则抛出异常
* 可以通过设置 hibernate 配置文件 hibernate.use_identifier_rollback 为 true,
* 使删除对象后, 把其 OID 置为 null
evict:
从 session 缓存中把指定的持久化对象移除

映射组成关系

pay类没有oid

在一对多的时候,最好先保存那个一,因为一的id是多的外键,如果先保存多,那么一保存后多还要执行update

一对多(比如一个A对多个B),那么在通过B来获得A时,得到的是A的代理。那么如果先获得B,然后关闭session再通过B获得A,会发生懒加载异常(类似load)。但是在session正常的情况下,是可以通过B去updateA的。
此外,若一个A关联多个B。A不能被直接删除。但是可以在A中设置Cascade属性,若选为“delete”则可以级联删除

在双向一对多时

  1. 声明集合类型时, 需使用接口类型比如能用set不能用hashset),, 因为 hibernate 在获取集合类型时, 返回的是 Hibernate 内置的集合类型, 而不是 JavaSE 一个标准的集合实现.
      1. 需要把集合进行初始化, 可以防止发生空指针异常

同样,多对一时,通过一来获取多也是延时加载方式,可能会发生懒加载异常。
一对一映射
基于外键映射的一对一
在一对一映射的时候,一边用多对一,但是设定unique=”true”,此时,在这一边会生成一个外键。在另一边选用一对一,需要设定的是,该类中的属性名name,对应的映射的全类名class,以及在映射类中外键对应的属性名property-ref(不设定这个的话,就会映射到对方类的主键而不是外键上)举例:
A类中属性b与B类对应,B类中属性a与A类对应。
A类设定为多对一
name=”b” class=”B” column=”A数据表中的外键列名,比如叫X” unique=”true”此时在A的表中就会有一列X对应B的主键。
B设定为一对一
name=”a” class=“A” property-ref=”b”设置ref可以让产生对应时B的主键对应的是A中X那列,而不是A的主键(才能对的上)
这样从B查A不会有懒加载(因为B的表中没有X这一列,需要去A中查,就初始化了A)
只在其中一边放外键X有利于管理,(如果两边都有外键,很容易出现错位)
基于主键映射的一对一

即两端都用one-to-noe。一端的generator设定为foreign,再用param设定具体哪个元素。这样就可以使自己的主键跟随对方而生成。举例:
在A中


b


在B中

这样的话,对应的两个表中,一定是B表先保存A才能跟着保存
多对多映射
使用中间表映射,必须有一边要设定inverse=“true”
在B中



A中相反,注意中间表明要一致,然后设置inverse。以及key中的列名要与对方的manytomany的列名对应
加了inverse那边不能用来添加关联关系,加不进中间表的

HQl

hql是面向对象的查询语句
Select/update/delete…… from …… where …… group by …… having …… order by …… asc/desc

from后的内容不是表名,而是类名如Customer cu,其中还能使用对象.属性,如cu.id 使用站位符号?或者用站位名字(冒号加展位名)
String hql=”select name FROM Category ca where ca.id=:kkk”;
Query query=session.createQuery(hql);
query.setInteger(“kkk”, 2);
List list=query.list();
System.out.println(list.get(0));用select,返回的则是查询到的对象,也可以select多个,不过这样的话list里面应该是object数组
如果不想返回数组,可以用

String hql = "SELECT new Employee(e.email, e.salary, e.dept) "
                + "FROM Employee e "
                + "WHERE e.dept = :dept";
        Query query = session.createQuery(hql);

        Department dept = new Department();
        dept.setId(80);
        List<Employee> result = query.setEntity("dept", dept)
                                     .list();

这种方式,不过前期是Employee中有对应的构造器
可以用query.setFirstResult(a).setMaxResult(b)设置从结果中第a个开始,拿最多b个(因为可能从a开始数总共不够b个)

在配置文件里可以用query标签设置HQL语句(个人认为意义不大)

Spring

在创建ApplicationContext容器时,会对配置文件中所有的类实例化,调用构造函数(如果有配置属性也会调用相应的set方法)

如果在配置文件中有属性却没有相应的set方法,则会出错

getBean的方法可以用getBean(“beanID”),也可以用getBean(类.class)但是后者必须保证该类只有一个bean

用xml配置bean时,在配置构造器时可以用参数类型以区分重载的构造器,也可以使用index指明传入顺序
如果自面值有特殊字符,用

Autowired

注释的方式:
需要在配置文件加

自动装配这个是识别类名,所以如果同一个类有两个bean会出错。

但是如果是在set方法上用autowired,有另一个层意义。例子:
对setA进行autowired,但是现在只有两个bean,这两个bean都是继承自A,分别为AA与AA2,那么会报错。但是当AA把bean id设置为A,则不会报错。(如果只有AA继承自A,那么也不会报错,但得不到bean)

如果有个beanB,但是想在变量A上用autowired装配,那可以在autowired下加一个@qualifer如图

Xml的方式:
用autowired属性指定自动装配的方式,byName根据bean的名字(id)和当前bean的setter风格的属性名进行自动装配
byType根据bean的类型(class)和当前bean的属性的类型进行自动装配
byType必须保证该类只有一个bean
ApplicationContextAware接口
Spring容器会检测容器中的所有Bean,如果发现某个Bean实现了ApplicationContextAware接口,Spring容器会在创建该Bean之后,自动调用该Bean的setApplicationContextAware()方法,调用该方法时,会将容器本身作为参数传给该方法——该方法中的实现部分将Spring传入的参数(容器本身)赋给该类对象的applicationContext实例变量,因此接下来可以通过该applicationContext实例变量来访问容器本身。

Spel

字面值 ”#{‘字面值’}”
对象 “#{对象名}”
其他对象的属性 “#{类.属性}”
静态属性 “#{T(全类名).静态属性或方法}”
运算符 在{}内使用,可以使用三目运算符?:

泛型依赖注入
有一个父类A一个父类B(没有配为bean),都是泛型的,其中父类B中依赖泛型的父类A,:
@Autowired
Protected A a;
然后在父类B中有一个方法打印a。
而A和B都有子类,分别为As与Bs(不写自己的方法)实现的泛型相同,都配为组件。最后在Main中getBean(Bs),并调用那个打印方法,打印的是Bs的信息(因为As是具体的型,所以自动装配时也装配了A对应型的子类)

AOP

导jar包

在配置文件加入aop命名空间

切面首先要加入IOC称为bean,需要声明为切面

add还可以改为*来通配
public int也可以一起化为一个*
传参可以统一化为两个点.. 只能是两个,不管参数多少,当然也可以单独把参数化为*
注释中的地址可以用一个final String代替,如
final String a=”execution(* *(int,int))”;
@AfterReturning(a)

After为后置通知,无论方法是否正常运行都要通知,而且无法获取运行结果
AfterReturning为返回通知,只在方法正常运行后通知,可以获取运行结果
事物
一组行为,要么都做,要么都不做。
用@transactional注解

内容概要:本文系统介绍了算术优化算法(AOA)的基本原理、核心思想及Python实现方法,并通过图像分割的实际案例展示了其应用价值。AOA是一种基于种群的元启发式算法,其核心思想来源于四则运算,利用乘除运算进行全局勘探,加减运算进行局部开发,通过数学优化器加速函数(MOA)和数学优化概率(MOP)动态控制搜索过程,在全局探索局部开发之间实现平衡。文章详细解析了算法的初始化、勘探开发阶段的更新策略,并提供了完整的Python代码实现,结合Rastrigin函数进行测试验证。进一步地,以Flask框架搭建前后端分离系统,将AOA应用于图像分割任务,展示了其在实际工程中的可行性高效性。最后,通过收敛速度、寻优精度等指标评估算法性能,并提出自适应参数调整、模型优化和并行计算等改进策略。; 适合人群:具备一定Python编程基础和优化算法基础知识的高校学生、科研人员及工程技术人员,尤其适合从事人工智能、图像处理、智能优化等领域的从业者;; 使用场景及目标:①理解元启发式算法的设计思想实现机制;②掌握AOA在函数优化、图像分割等实际问题中的建模求解方法;③学习如何将优化算法集成到Web系统中实现工程化应用;④为算法性能评估改进提供实践参考; 阅读建议:建议读者结合代码逐行调试,深入理解算法流程中MOAMOP的作用机制,尝试在不同测试函数上运行算法以观察性能差异,并可进一步扩展图像分割模块,引入更复杂的预处理或后处理技术以提升分割效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值