明天就是毕设答辩了,毕设课题是基于SSH框架做的一个网站,用eclipse作开发工具,以MySQL作为数据库。2月底自学(其实是复习)SSH3大框架及整合,3月开始做毕设,4月中基本完成,但还是有很多地方做得并不好,很多功能还能再完善一下。这1个半月遇到了很多莫名奇妙的报错,有些找到原因,有些却没有,不管怎样,我每次都把问题及自己的解决办法记下来了。这次做个汇总,算是给这个毕设做个交代,给自己大学画下句号。(虽然项目很渣但还是想在答辩过后将其推上github的)
错误信息1:
struts.xml报错
The content of element type "struts" must match "((package|include|bean|constant)*,unknown-handler-stack?)".
原因:
说明xml不符合dtd规范,意思是struts下的子节点只能是package、include、bean或者constant
解决:
拦截器interceptor要放到package里
错误信息2:
数据库无法更新,报错
Could not find a getter for product in class com.ssh.model.Article
原因:
映射关系在hbm.xml中写好了,但是实体类中还没有进行定义
解决:
需要在"one"处定义集合private Set<Article> article = new HashSet<Article>();
在"many"的实体类中private "one" 一个对象
最后都要实现getter setter
错误信息3:
页面无法打开
org.springframework.beans.NotWritablePropertyException: Invalid property 'sessionFactory' of bean class [dao.impl.UserDaoImpl]: Does the parameter type of the setter match the return type of the getter?
原因:
DAO没有继承HibernateDaoSupport
解决:
UserDaoImpl extends HibernateDaoSupport
用JdbcTempalte或HibernateTempalte操作数据库。
参考:http://blog.csdn.net/xinxin19...
错误信息4:
图片无法显示,路径怎么改都无效
原因:
不详
解决:
原本图片在asset/image文件夹内,分别写了几种图片路径,结果都不行
包括:asset/image/xx.png 、 ../asset/image/xx.png 、 /asset/image/xx.png 、WebContent/asset/image/xx.png
于是参考了几个其他同学做的项目,他们都是直接在WebContent下创建img文件夹,把图片放在里面,路径直接img/xx.png,我打算尝试一下他们的,但也不想放弃自己的,于是把第一个的图片放到新建的img文件夹内,其余照旧。
结果是:asset/image/xx.png有效,img/xx.png有效。
只有../asset/image/xx.png无效。
暂时不知道原因
PS:图片路径不能直接用struts标签写,要在img标签内写,如下:
<img src="<s:property value="#a.pic"/>">
错误信息5:
在业务层实现类中调用DAO接口的方法时,对象报错
Multiple markers at this line - Cannot make a static reference to the non-static method findAll() from the type CategoryDao
原因:忘记了先注入DAO的对象
解决:
//注入DAO
private CategoryDao categoryDao;
public void setCategoryDao(CategoryDao categoryDao) {
this.categoryDao = categoryDao;
}
错误信息6:
Resource is out of sync with the file system:../../Back/css/boostrap.responsive.min.css
原因:
这是文件系统不同步的问题,是因为在eclipse或mycelipse之外对工程中的resource进行修改引起的(或者是由不同的系统间对文件进行修改引起的);但是,有时没有在eclipse或mycelipse之外进行修改,也会报类似的错误。
解决:
需要手动刷新一下资源管理器。
(1)在eclipse或mycelipse中,工程目录右键,选择F5(refresh)
(2)设置eclipse或mycelipse自动刷新。
通过Window->Preferences->General->Workspace,选中Refresh automatically。
场景:关于搜索功能问题,输入“三星”关键词,点击“搜索”按钮,报错!
错误信息7:
Not all named parameters have been set: [三星] [select count() from Article where title like:三星]; nested exception is org.hibernate.QueryException: Not all named parameters have been set: [三星] [select count() from Article where title like:三星]
原因:
hql语言格式写错,应该用%包住传过来的关键词,一步到位,不建议用:
错误:String hql = "select count(*) from Article where title like :"+title;
正确:String hql = "select count(*) from Article where title like '%"+title+"%'";
%用于替代一个或多个字符
错误信息8:
首次用户/管理员登陆失败后,输入正确账号密码点击登陆,跳转报错404
(这个也是很坑爹。。)
原因:
spring bean出问题, scope="prototype" 会在该类型的对象被请求时创建一个新的action对象。如果没有配置scope=prototype则添加的时候不会新建一个action,他任然会保留上次访问的过记录的信息。
<!-- scope默认采用的是单例模式,scope="prototype" 可以保证 当有请求的时候都创建一个Action对象,保证Struts的Action线程安全 -->
参考文章:http://blog.csdn.net/qq_31573...
原文:
检查后发现在action中没有加入@Scope("prototype"),@Scope("prototype")的意思是每次都会创建一个新的action,这样就不会有冲突了
如果不加这句话,那么像我上面这样刷新页面想再次插入数据的时候就还会使用上一个的action实例
起初我还以为是因为hibernate里session的问题,session对象没有关闭,因为我用的是hibernateTemplate对象,后来我发现hibernateTemplate这个东西内部实现就封装了session.close方法!Spring会为我自动在beanFactory中新建实例,如果我不管理它们的周期不全都乱套了
错误信息9:
[org.apache.struts2.dispatcher.Dispatcher]Could not find action or result: /SSH_Website/Back/article_findAll.action No result defined for action com.ssh.action.ArticleAction and result input - action - file:/E:/eclipse/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/SSH_Website/WEB-INF/classes/struts.xml:37:63
at com.opensymphony.xwork2.DefaultActionInvocation.executeResult(DefaultActionInvocation.java:371)
原因:
来自form表单一个属性没有设置,是上传文件必须具备的
解决:
enctype="multipart/form-data"
场景:关于<s:if test="表达式"></s:if>中test无法判断"性别是否为男"的问题
原因:
A:<s:if>判断字符串的问题:
1、判断单个字符:<s:if test="#session.user.username=='c'">
这样是从session中取出username的值,并且判断其是否为c,但是这样判断是不正确的,这样判断的话,根本判断不出来,要改成下面这样:
<s:if test="#session.user.username=='c'.toString()">
这样判断才能正确判断,至于原因我也不知道,在网上看到struts2中可能它判断的是char类型。
2、判断字符串:<s:if test="#session.user.username=='milo'">
这样写的就是判断username是不是milo,是String的判断,这个是不用加toString()的。
3、判断数值:<s:if test="#session.user.username==0">
这样写的就是判断username是不是0,是int的判断。
解决:
因此:<s:if test="#session.existUser.sex=='男'">是错的
要改为<s:if test="#session.existUser.sex=='男'.toString()">
某些情况下,你可能会和我一样傻,就是update了用户的某个信息(例如修改密码),然后其他地方不填写的话(如email),则数据表里这些地方就会从null改为空,反正就是空白。但我想在空白的时候添加一句“此人很懒,什么都不写”,却无法判断这个空白,用""都不行,而原理和上面一样。
<s:if test="#session.existUser.udesc==null">
<p>此人很懒,什么都不写</p>
</s:if>
<s:if test="#session.existUser.udesc==''.toString()">
<p>此人很懒,什么都不写</p>
</s:if>
2017-3-22
今天几个难点:用baseDao的前提下,如何写好离线查询。
1.模糊查询时,关键词需要用%包住,再用like("字段名",xxx) (xxx必须已经包含%)
2.种类和产品是1对多的关系。(Product表中有外键cno,Product和Category是多对1的关系
但是总报错,原因是,第一,我传过来的是new Object[]{cid}-->Object[] param是数组
然后,
DetachedCriteria criteria = DetachedCriteria.forClass(c);
criteria.add(Restrictions.eq("cno", param));
以上语句几处错误:
第二,由于cno是外键,要靠种类的类查询,因此在forClass后声明种类category
( 即.createCriteria("category") )
第三,由于Product的cno是虚假的,它要通过直接查种类再级联回这个外键cno,因此前面声明了category后,这里就可以写eq("cid",??);
第四,而因为第一点,所以?中是param的话就报错
java.lang.Integer cannot be cast to [Ljava.lang.Object;
类型转换错误,实际是 Integer 类型的,不是数组
因此,将第一点改为int,包括
业务层的new Object[]{cid}改为cid,
baseDao传递的Object[] param参数改为int cid,
Restrictions.eq("cid", cid)
因此,最后正确的baseDao写法是:
public List<T> findByPage(Class<T> c, int begin, int pageSize,int cid) {
// TODO Auto-generated method stub
DetachedCriteria criteria = DetachedCriteria.forClass(c).createCriteria("category");
criteria.add(Restrictions.eq("cid", cid));
List<T> list = this.getHibernateTemplate().findByCriteria(criteria,begin,pageSize);
return list;
}