又一个问题1、
当在几种框架集成的时候,在调用HibernateDaoSupport中的某个方法时会出现:
java.lang.NoSuchMethodError: antlr.collections.AST.getLine()I 的错误。这是因为在struts2自带的antlr-2.7.2.jar包的版本较低。
需要换成antlr-2.7.6.jar。其实在项目中已经存在了antlr-2.7.6.jar这个包,现在唯一需要做的就是删除antlr-2.7.2.jar包。
选择windows---preferences---在文本框中搜索struts 2(中间有空格)---选择struts 2---选择antlr-2.7.2.jar---Remove---OK。
又一个问题2
使用Spring中的AOP技术代理了Service(实现声明式事务管理),然后将Service通过IoC注入给Action.未加入 Struts时一切正常,但是加入Struts后出错,提示信息大意为无法将被代理的Service对象注入给Action,异常为 ClassCastException.
【分析原因】
ClassCastException表明这是一个类型不匹配错误,再看详细的出错信息:"Can't convert $Proxy1 to com.xaccp.XxxService"(大体是这个意思,原文记不清了),说明在Action中需要的类型为com.xaccp.XxxService,而实际传入的是$Proxy1。
接下来应该想到Service对象是被Spring代理的,Spring中有两种实现代理的方法:JDK提供的动态代理和CGLIB。
CGLIB的实现原理是动态生成目标类(Target)的子类,如果一个类采用CGLIB代理的,生成的子类类名一般为 com.xaccp.XxxService$$EnhanceByCGLIB$xxxx的格式,并且根据父子类转换的规则,在要求目标类的地方,如果传入生成的代理类不会发生ClassCastException异常。
而动态代理的实现原理是动态生成一个与目标类显示相同接口的类,生成类类名就是$Proxy1这样的格式,在要求目标类的地方,如果传入生成的代理类就会发生上面的错误。
再看学生写的Service类,果然实现了一个接口,那么默认的情况下,如果类存在接口,Spring就会采用动态代理来实现AOP,于是发生了上面的错误。
【解决方案】
分析清楚原因以后解决方案就出来了:
最简单的一种方案就是去掉Service实现的接口,那么Spring会采用CGLIB来实现AOP。但是这个方案显然破坏了代码的结构
最应该采取的一种方案是在Action中不要直接将属性声明为Service类,而是声明为其接口,这样Spring就可以将实现了同样接口的$Proxy1代理类注入进来。并且体现了面向接口编程的原则。
还有一种方案就是在设置代理时指明proxyTargetClass属性为true,强制Spring采用CGLIB进行代理,如下所示:
<bean class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property>
<ref bean="dummyService"/>
</property>
<property>
<value>true</value>
</property>
<property>
<ref bean="tm"/>
</property>
<property>
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
又一个问题3
tomcat:
at:com.opensymphony.xwork2.util.FileManager$FileRevision.needsReloading
练习时发现只要把struts.xml的约束struts.devMode状态改为true就会报这个错误,而改为false就ok。
解决问题:
tomcat 的解压路径中不能包含空格,刚开始我的路径是在D://tomcat 6.0/;其中tomcat 和6.0之间有空格。之后我把他改成了D://ttomcat6.0/之后问题解决。
又一个问题4
Unable to load configuration. - bean - jar:file:/D:/WIN7/apache-tomcat-6.0.26/webapps/DoAjax/WEB-INF/lib/struts2-spring-plugin-2.1.8.1.jar!/struts-plugin.xml:29:132
解决:Struts 2 版本不一致引发的异常!
struts2-core-2.0.9.jar 与 struts2-spring-plugin-2.2.1.jar 版本不一致!
又一个问题5、
在单独的使用Hibernate时,在Hibernate映射文件(*.hbm.xml)中配置好各个类的关系,然后再Hibernate配置文件(hibernate.cfg.xml)中添加属性可以自动在数据库中创建表结构(注:只能创建表,而非创建库)。
主要代码如下:
<!--自动在数据库中建立表 -->
<property>create</property>
在我使用spring mvc 整合hibernate时,代码如下:
<property>
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hbm2ddl.auto">create</prop>
</props>
</property>
</bean>
运行程序,提示 * 表不存在,可见自动建表并未成功。
解决方法。
<property>
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">create</prop>
</props>
</property>
</bean>
分析:可能是在spring配置文件中,并不识别“hbm2ddl.auto”项,所以该项配置根本没起到作用,而使用“hibernate.hbm2ddl.auto”,spring的配置文件是可以识别的,问题得到解决。期待有更权威的解释。
又一个问题6、
struts2+spring2.x+hibernate3.x 懒加载异常:org.hibernate.LazyInitializationException: failed to lazily initialize
Hibernate的Lazy初始化1:n关系时,必须保证是在同一个Session内部使用这个关系集合,不然Hiernate将抛出异常:org.hibernate.LazyInitializationException: failed to lazily initialize of....
两种处理方法:
一、设置lazy=false,此方法不再累述。
二、用OpenSessionInViewFilter过滤器,注意hibernateFilter过滤器和struts2过滤器在映射时的先后顺序。同时要配置事物处理,否则会导致session处于只读状态而不能做修改、删除的动作。
即在web.xml文件中如下配置:
<!-- Spring ApplicationContext配置文件的加载目录。 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:spring/applicationContext.xml</param-value>
</context-param>
<!-- 解决延迟加载的问题 -->
<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
</filter-class>
</filter>
<!-- 继承Struts2的FilterDispatcher类,具备GBK等编码设定功能与struts2的action过滤功能。 -->
<filter>
<filter-name>struts2</filter-name>
<filter-class>
com.iman.nrms.opm.web.common.FilterDispatcher
</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>GBK</param-value>
</init-param>
</filter>
<filter>
<filter-name>struts-cleanup</filter-name>
<filter-class>
org.apache.struts2.dispatcher.ActionContextCleanUp
</filter-class>
</filter>
<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>struts-cleanup</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Hibernate 允许对关联对象、属性进行延迟加载,但是必须保证延迟加载的操作限于同一个 Hibernate Session 范围之内进行。如果 Service 层返回一个启用了延迟加载功能的领域对象给 Web 层,当 Web 层访问到那些需要延迟加载的数据时,由于加载领域对象的 Hibernate Session 已经关闭,这些导致延迟加载数据的访问异常。而Spring为我们提供的OpenSessionInViewFilter过滤器为我们很好的解决了这个问题。OpenSessionInViewFilter的主要功能是使每个请求过程绑定一个 Hibernate Session,即使最初的事务已经完成了,也可以在 Web 层进行延迟加载的操作。OpenSessionInViewFilter 过滤器将 Hibernate Session 绑定到请求线程中,它将自动被 Spring 的事务管理器探测到。所以 OpenSessionInViewFilter 适用于 Service 层使用HibernateTransactionManager 或 JtaTransactionManager 进行事务管理的环境,也可以用于非事务只读的数据操作中。
request-->open session-->打开连接、开始事务-->持久操作-->渲染(关闭连接、session)-->response 其中一些过程省略了,不是很关心。
又一个问题1. 也是最讨厌的:NullPointerException。在整合SSH中经常出现的莫过于NullPointerException了,导致这种错的原因很多。bean的注入问题,也就是spring的配置文件中的错误;struts2和spring的整合问题,如果整合出现问题也会出现这种错误。关于第二种情况要多说一点了,因为今天我遇到了这个错误。其实也是常识性的错误struts2没有整合spring的应用。
这里简单说一下struts2和spring整合的问题:首先struts2方面应该引入struts2-spring-plugin-2.2.1.jar和其他struts2 所必需的包,然后就是配置文件中struts.xml应该加入:<constant value="org.apache.struts2.spring.StrutsSpringObjectFactory" />表示和spring的整合。
我觉得还是有必要详细的描述一下今天我遇到的问题:我通过spring配置的action类中的方法通过Junit可以测试成功,但是jsp页面访问的时候产生了NullPointerException,费了半天的劲才发现是这种错误!!不过错误解决了心里听高兴的!!
又一个问题2. java.lang.NoSuchMethodError: antlr.collections.AST.getLine()。这个错误也挺容易出现的。这个错误产生的原因是将阿宝的冲突。antlr-2.7.6.jar在struts2和hibernate中都有,分别使用框架的时候没问题但是如果整合起来就会出现这样的问题,去掉一个较低版本的就可以了!
又一个问题3. 配置拦截器后表单参数不能实例化!!这是什么原因呢?这个问题的原因涉及到struts的自动装载机制,但是解决方案挺简单的,将struts2的默认拦截器也配置上!!如果应用中没有配置拦截器表单传递过来的参数是不能自动装载成为对象的!!
又一个问题 4. hibernate的session管理问题:Write operations are not allowed in read-only mode (FlushMode.NEVER/MANUAL) !这是使用spring的opensessioninview引起的异常!!网上的方案挺多的,我使用了这种方案:
还有一种方案要在spring的配置文件中配置:
又一个问题5.关于hibernate的复杂交叉的映射关系。今天遇到了org.springframework.orm.hibernate3.HibernateSystemException: IllegalArgumentException occurred while calling setter of org.blog.po.User.ulog; nested exception is org.hibernate.PropertyAccessException: IllegalArgumentException occurred while calling setter of org.blog.po.User.ulog 这样的错误(错误类型一样,但是具体信息不一样)。错误信息中提示type mismatch:类型不匹配。我就一直纳闷因为我检查了好几遍,完全没问题呀!最后还是找到了问题的根源。我先说明一下这个关联关系:关联对象,用户和组;用户可以创建一个组,一个组中有多个用户。听起来还是蛮简单的,但是错误出现了。
分析一下原因:因为当初我考虑到效率的问题用的是双向的关联关系,其实这也就是出错的根源,用户与组之间存在两种关联关系,hibernate不能分清楚用户谁是创建者谁是用户,所以出现了这样的问题。干脆抛弃双向的关系,双方都使用单向的关系,问题解决了!!
又一个问题 6.这个错误信息是这样的:nested exception is org.hibernate.exception.SQLGrammarException: Could not execute JDBC batch update。我到网上搜了一下这个个问题的答案:(1)因为 Hibernate Tools (或者 Eclipse 本身的 Database Explorer )生成 *.hbn.xml 工具中包含有 catalog="***" ( *表示数据库 名称)这样的属性,所以数据库迁移到其它数据库就会产生这样的错误。(2)数据表中的字段与hibernate映射文件中的属性配置冲突,造成插入无法进行。
最后我说一下我的错误:我的错误其实和第二种类似,我创建了一个名为Limit的类,不知道这是mysql的关键字,还是hibernate的关键字,hibernate没有帮我自动生成这个limit数据表,所以...
又一个问题
7.关于 org.hibernate.HibernateException: illegally attempted to associate a proxy with two open Sessions的错误!!这个错误也是让我煞费苦心,搞了差不多将近两个多小时!!试尽了我想到的可能解决这个问题的方法,但是毕竟还是小鸟一只...结果你懂得!!但是老鸟还是遍地飞呀...
哦哦...忘了说明错误出现的场景了:组织---个人(多对多关系),更新组织中成员的时候出现了这个错误,更新我用的update方法!!好吧下面说一下解决方案:只要把update换成merg就ok了!!
简单介绍一下merge方法:
我觉得我还有必要记录一下我解决错误时的方案:我首先想到的是hibernate懒加载惹的祸,因为我在hbm配置文件中配置了lazy懒加载。但是问题还是没有解决。于是我把update(Team team, String tid)方法修改为update(Set<User> users, String tid),问题还是不得解决,于是完全否定了是懒加载的问题!但是对于上面的这种方案我还是不太理解,SSH的session问题肯定是一个大问题!!
未完待续......
又一个问题、No identifier specified for entity
实体类中没有主键定义。
又一个问题报错:Data truncated for column 'parent_id' at row1
如果在运行系统.sql脚本文件时报:Data truncated for column 'parent_id' at row1 错误。
主要原因是在建表的列为特定类型,而所插入的数据类型没与其字段一一对应。
比如本来建表中字段一个int类型的,而你在insert表时有个字段写成了string类型,则就报此错误了。
又一个问题
如果hibernate不执行save等方法考虑spring事务管理没配置好
这个挺好用的。。每次改改就可以了
<!-- 配置事务管理器 -->
<bean
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property>
<ref bean="sessionFactory" />
</property>
</bean>
<!-- 配置事务的传播特性 -->
<tx:advice transaction-manager="transactionManager">
<tx:attributes>
<tx:method propagation="REQUIRED" />
<tx:method propagation="REQUIRED" />
<tx:method propagation="REQUIRED" />
<tx:method propagation="REQUIRED" />
<tx:method propagation="REQUIRED" read-only="true" />
<tx:method propagation="REQUIRED" read-only="true" />
</tx:attributes>
</tx:advice>
<!-- 配置哪些类哪些方法使用事务 -->
<aop:config>
<aop:pointcut expression="execution(* com.zz.dao.*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="allManagerMethod" />
</aop:config>
又一个问题
java.sql.BatchUpdateException: Cannot add or update a child row: a foreign key constraint fails (`myshop`.`t_product`, CONSTRAINT `FKA91FC0248049AD0` FOREIGN KEY (`productCategory_id`) REFERENCES `t_product_category` (`id`))
这种问题是外键关联引起的。主表中外键的引用一定要先有值。才能插入主表。否则就会报这个错误
又一个问题
hibernate、jpa is not mapped
假设我们的表结构为:(mysql)
Sql代码
CREATE TABLE `t_creditcard` (
`id` int(11) NOT NULL auto_increment,
`cardName` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `t_creditcard` (
`id` int(11) NOT NULL auto_increment,
`cardName` varchar(20) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
写法一:
Java代码
@Entity
public class CreditCard{
private Long id;
private String name;
}
//测试代码1
CreditCard cc = new CreditCard();
cc.setCardName("测试卡");
cc = ccDao.persist(cc);
@Entity
public class CreditCard{
private Long id;
private String name;
}
//测试代码1
CreditCard cc = new CreditCard();
cc.setCardName("测试卡");
cc = ccDao.persist(cc);
日志输出Hibernate: insert into CreditCard (cardName, id) values (?, ?)
该写法适用于表名和实体类名相同,如果表名和类名不用,该写法则不能正确插入。
写法二:
Java代码
@Entity(name="t_creditcard")
public class CreditCard{
private Long id;
private String name;
}
//如果你的dao中有类似的查询
//测试代码2
session.createQuery("from CreditCard c where c.id=10001").list();
//测试代码3
session.createQuery("from t_creditcard c where c.id=10001").list();
@Entity(name="t_creditcard")
public class CreditCard{
private Long id;
private String name;
}
//如果你的dao中有类似的查询
//测试代码2
session.createQuery("from CreditCard c where c.id=10001").list();
//测试代码3
session.createQuery("from t_creditcard c where c.id=10001").list();
测试代码1日志输出为:Hibernate: insert into t_creditcard (cardName, id) values (?, ?),可以正确插入。
测试代码2日志输出为:org.springframework.orm.hibernate3.HibernateQueryException: CreditCard is not mapped [from CreditCard c where c.id=10001];
所以@Entity 的name对应的是实体别名。
测试代码3通过。
所以如果你的库表名和你的实体类名不同而且还想在使用HQL或者JPQL的话,正确的方法应该是:
Java代码
@Entity
@Table(name="t_creditcard")
public class CreditCard{}
@Entity
@Table(name="t_creditcard")
public class CreditCard{}
该写法以上测试全部通过。
一个生气的问题
No result defined for XXXAction and result INPUT
<input type="text" name="receiverLoginID" value="<%=name%>"/>
当 name值为NULL时,就出这个错了,所以你可以在当前页面加入以下标签
<div style="color:red">
<s:fielderror />
</div>
它就会显示拦截器的错误,并在struts的XML中对应action里加如
<result name="input">/error.jsp</result>
让他把错误返回到该页面就可以了
在jsp页面中不能取set类型的值再传回给struts否则。你明明没有定义input这个返回类型。他也这样提示。。而且它不会执行你要去执行的方法。。而是直接弹出这个提示
又一个问题1、
这个错误我一共遇到过两次,一直没有找到很好的解决方案,这个错误产生原因相信大家都知道,因为在hibernate中同一个session里面有了两个相同标识但是是不同实体.
一开始按网上说的用session.merge(Object)报了一个错,可能是没有用好,改用 session.clear(); session.update(user);这样就OK了,
方法为:
package org.springframework.orm.hibernate3.support;
...
public void modifyByMerge(User user) {
Session session = getHibernateTemplate().getSessionFactory().
getCurrentSession();
session.clear();
session.update(user);
}
...
项目用的是spring + hibernate所以得用getHibernateTemplate().getSessionFactory().getCurrentSession();得当前Session
错误描述:
javax.servlet.ServletException: org.springframework.orm.hibernate3.HibernateQueryException: could not resolve property: sort1 of: com.crm.model.product.Product [From com.crm.model.product.Product as product where product.sort1=1];
出现错误原因:HQL语句错误,查询关键词出错,HQL语句中的关键字在hibernate映射文件中查找不到。
解决方法:检查HQL语句,和hibernate映射文件中的属性一一比对!