SSH框架

1、使用hibernate进行更新操作时,首先调用了findById方法获取要修改的对象,此时session没有被关闭,接着重新创建一个对象,将要修改的属性值赋值给这个对象。调用修改方法抛出如下异常:

org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session

原因:在session缓存中已经存在一个与当前传递进来的修改对象具有相同标识符(主键)的对象。Hibernate的机制是只能存在一个具有唯一标示的对象,否则增删改就会出错。

解决办法:

:在使用过滤器/拦截器时,每次开启session,操作后就关闭session。

session.evict(Object object),从缓存中清除指定的对象。

ƒsession.clear(),是将session缓存中的对象全部清除,杀伤面太大了,不建议使用。

 

2、HibernateSessionFactory类中有一个线程ThreadLocal类的对象,它用来分配session对象,经测试后发现,由它每回获取的session都不同,有时为空,有时可以得到之前存进去的session对象。

 

3、如果使用struts+hibernate框架实现数据库的增删改,使用过滤器去开启和提交事务时,有时增删改会没有效果,因为action没有被过滤器过滤,这个使我困惑了很久,因为之前的项目都可以被过滤到,后面我想用拦截器拦截action,在拦截器中开启和提交事务,试验之后发现此法可行。

 

4、使用hibernate+struts框架开发项目时,系统抛出如下异常:

Exception

java.lang.reflect.InvocationTargetException

root Cause:

java.lang.NoSuchMethodError: antlr. Collections.AST.getLine()I

 

原因:由于我用的是MyEclipse自动生成的struts和hibernate类库,hibernate中有个antlr-2.7.7.jar,而struts中有个antlr-2.7.2.jar。异常的原因就是说没有找到antlr.Collections.AST类中的getLine()方法,高版本的jar中有getLine()方法,而低版本中没有getLine()方法,系统默认使用的是低版本的jar包。

解决办法:去除struts类库中的antlr.jar包即可,还需要清理并构建这个项目,因为有的项目的配置信息一时更改不过来。

 

5、Struts的类型转换器用于将String类型转化为指定的数据类型,还可以将指定的数据类型转化为String类型。开发项目时很方便。

实现方法:

:新建一个类继承StrutsTypeConverter类,实现其中的两个抽象方法,作为转换器类。

‚:新建局部属性文件或者全局属性文件

 

 

局部属性文件:放置在相关action类同级目录下,文件名格式:action类名-conversion.properties

里面存放键值对,如:hobbies=util.ListConverter

hobbies就是要转化的属性名,util.ListConverter就是转换器类的完全限定名。

全局属性文件:放置在src目录下,文件名格式:xwork-conversion.properties

里面存放键值对,如:java.util.Date=util.DateConverter

java.util.Date就是要转化的数据类型,util.DateConverter

就是转换器类的完全限定名。

注意:如果我们使用<s:property/>标签,那么它会调用转换其中的convertToString(),如果使用EL表达式,那么就不会调用该方法了。

 

6、针对类型转换出错的处理--在页面上显示友好提示:

类型转换出错时,要抛出一个运行时异常,程序会根据建立的属性文件,显示错误提示。

实现方法:

:新建局部属性文件或者全局属性文件

局部属性文件:放置在相关action类同级目录下,文件名格式:action类名.properties

里面存放键值对,如:invalid.fieldvalue.time=mistake

invalid.fieldvalue.time就是出错的字段名,mistake是错误提示信息。

全局属性文件:放置在src目录下,文件名格式:message.properties,属性文件的名称不作要求。

还要在struts.xml中配置一个常量:

<constant name="struts.custom.i18n.resources" value="message"/>

属性文件中存放键值对,如:xwork.default.invalid.fieldvalue=fieldname is {0} is error

这是固定的格式,{0}代表错误的字段名,系统会自动赋值。

fieldname is {0} is error 便是提示信息。

 

7、Struts框架有类似于html的标签,但是它有一定的格式,

但是我们可以在struts.xml中配置一个常量,去掉它的格式。

     <constant name="struts.ui.theme" value="simple"/>

 

8、当我们显示错误信息的时候,会发现错误信息会以列表的形式显示,这样就不美观了,达不到我们想要的标准。所以我们可以用另外的方式输出错误信息。

例如我现在增加了两个错误信息:

this.addFieldError("username","用户名太长!");

this.addFieldError("username","2222!");

那么我就可以使用以下四种方法输出错误信息:

    <s:property value="errors.username[0]"/>  

   ‚ <s:property value="fieldErrors.username[0]"/> 

   ƒ ${errors["username"][0] }

   4 ${fieldErrors["username"][0] }

原理:在值栈中有fieldErrorserrors两个对象,这两个对象中存储着错误信息,利用<s:debug/>可以观察到,这两个对象其实就是map数据类型的。

获取map数据的方法

 

 

 

9、Struts上传文件

jsp部分:

 

 

struts.xml部分:

 

 

action部分:

 

 

 

注意:

文件对象名就是表单文件控件的name

文件类型的命名=文件对象名+FileContentType

文件名称的命名=文件对象名+FileName

 

10、struts下载文件

jsp部分:

 

 

struts.xml部分:

 

 

action部分:

 

 

 

11、两级联动

演示:

 

 

 

 

 

 

 

原理:

将数据库中的数据封装成对象,然后将对象转化为json数据,在客户端用异步获取后台的json数据即可。

客户端jsp页面:

 

 

 

 

 

 

 

后台:

 

 

 

 

注意:在js中如果某个元素还未被加载,那么只可以获得该元素的引用,不能对该元素进行绑定事件。

 

13、struts框架中使用json

客户端:

 

 

 

Struts.xml:

 

 

UserAction:

 

 

注意struts类库里面没有提供ezmorph-1.0.6.jar文件,所以要手动添加。

 

14、hibernate中的cascade属性

Cascade属性是存在于set标签中,用来做级联删除和保存。

它的值有以下几种:

默认值是none,不做级联动作;

save-update:级联保存

delete:级联删除

all:级联保存和删除

 

注意:属性名称和属性值都严格需分大小写

 

15、hibernate中的inverse属性

修改街道对应的区道信息:

 

 

修改后会发现程序执行了两次修改操作:

 

 

原因:

区道与街道是一对多的关系;

由于Hibernate是双向维护外键,所以当修改区道中的街道时,会修改一次外键;在修改街道中的区道时,又会修改一次外键。

这样就会产生效率慢的问题,因为如果执行两次修改,那么第二次是无用的操作。利用inverse属性可以解决这一问题。

 

在区道表的映射文件里面的set标签中设置inverse属性为true;

inverse的属性值如下:

默认值为false,表示我方不放弃维护外键的权利

true,表示我方放弃维护外键的权利

 

 

 

一个国家有一个主席,国家有很多人,主席不可能认识国家的所有人,但是国家所有人可以认识主席。

 

16、延迟加载

延迟加载分为类级别延迟和关联级别延迟。

类级别延迟:

使用load(),例如:

 

 

只有当使用这个对象时才会进行查询,如输出str和str.getName()时就会执行查询语句,但是str.getId()并不会进行查询。

关联级别延迟:

使用set标签中的lazy属性,lazy的属性值有true(默认值)、false、extra(极其懒惰,要什么才查什么);

懒加载的意思就是当你使用到对象中的关联对象时,才执行查询操作。

如当lazy=”true”时,当你使用set时才执行查询操作。

如当lazy=”false”时,当你获取District对象时,同时会查出所有的Street。

如当lazy=”extra”时,用什么查什么。

如我要查询set.size(),系统会执行一下的查询语句:

 

 

 

17、fetch属性

fetch的属性值有select(默认值)、join、subselect

fetch=”select”时,程序会先查询返回要查询的主体对象,然后根据lazy属性看是否懒加载。

fetch=”join”时,程序会将主体对象和关联对象用一句连接查询的sql同时查询出来,这样以来,懒加载就无用武之地了。

subselect和select一样,不会一开始就将关联对象查出来。

subselect与select的区别:

 

 

设置不执行懒加载;

select是根据关联外键的id,每一个对象发一个select查询,获取关联的对象。

执行的sql如下所示:

 

 

 

subselect是发送两条sql语句,一条是查询主体对象,而另一条是抓取在前面查询到的所有实体对象的关联集合。

执行的sql如下所示:

 

 

 

18、批量抓取

批量抓取的使用场景是查询出来一个集合,然后又查询每个集合对象中的集合。使用set标签中的batch-size属性实现。

 

数据库中只有5个区道信息;

设置batch-size=”5”,执行的查询语句如下:

 

 

 

 

 

 

 

 

而设置batch-size=”7xxx”,执行的查询语句如下:

 

 

由于发送sql数据的次数多少,所以batch-size的数值越大,效率就越高。

batch-size为4时,首先会有4个?号,接着一个查询语句会有1个?号。

 

19、QBC查询

格式:

 

 

 

qbc的统计查询得使用projection实现,有两种方式:

(1)

 

 

(2)

 

 

 

查看文档发现ProjectionList和Projection的关系如下所示:

 

 

 

 

 

可以使用groupProperty投影对结果集进行分组(使用SQL的GROUP BY子句),当你通过某个属性分组时,程序就会查询出该属性所对应的列名。

可以使用Property.forName()来表示投影,就是查询指定的字段。

创建别名有三种方式:

 

 

 

20、离线查询:

 

 

离线查询使用DetachedCriteria对象设置限制条件,然后再通过session获取Criteria对象。

离线查询的使用场景:例如Biz类和Dao类,在Dao类中利用session操作CRUD,如果你想在Biz中设置限定条件,如果不使用离线查询,那么势必得获取Criteria对象,如此一来又得获取session,有点麻烦。

但是使用离线查询的话,可以直接获取DetachedCriteria对象设置限定条件,然后再将这个对象传递到Dao中即可。

 

 

 

概念:

投影就是指部分字段,例如我只查询学生表中的姓名,这就叫投影。

CRUD是指在做计算处理时的增加(Create)、读取查询(Retrieve)、更新(Update)和删除(Delete)几个单词的首字母简写。

posted @ 2019-06-25 15:06  暹罗siam  阅读(238)  评论(0编辑  收藏  举报