三大框架到今天也基本上学完了, 感觉Struts最简单, 而Spring则主要是学设计模式, 而Hibernate不好把握。现将学习过程中遇到的一些问题及解决方案予以记录.........
1、 1、 java.lang.IllegalArgumentException: No bean specified
java.lang.IllegalArgumentException: No bean specified......
org.apache.commons.beanutils.PropertyUtils.getPropertyDescriptor
经查找原来是自己在ActionForm中如此使用: private SomeObject objectInstance
正确的做法是 private SomeObject objectInstance = new SomeObject(); 或者在reset()方法中进行New SomeObject().
2、 org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in ServletContext resource [/WEB-INF/classes/applicationContext.xml]: Invocation of init method failed; nested exception is java.lang.NoSuchMethodError: org.objectweb.asm.ClassVisitor.visit(IILjava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)V
这个问题整整困扰了我一整天, 上网时说是要将Spring中的asm-2.2.3.jar包然后重启。 我照做了仍然无效, 然而同样的工程在另外一个同学的电脑上运行又可以... ....
后来终于发现我在删除asm-2.2.3.jar包之后尽管重启tomcat,但是webapps下的那个工程还是之前的那个工程, 进入webapps目录下将其原来的工程删除再重新部署OK!
关于如何删除spring中的asn-2.2.3.jar的方式:
window——preferences——Project Capabilities——spring——选择2.0找到相应的.jar包进行删除。
^_^ ^_^ 为了避免在以后的开发过程中遇到此种问题, 我们可以抽取出一个通过测试的 SSH包组合。关于导出在myEclipse下导出这些包的方法: 在相关路径下寻找
与此相关的异常还有:
2.a : 信息: Servlet action is currently unavailable
2.b : action is null
3、Spring中集成Hibernate
我是先导入Spring,后导入Hibernate的。 老师那种先Hibernate则需要在手动在applicationContext.xml中配置hibernateSessionFactoryBean。
class org.springframework.orm.hibernate3.localsessionfactorybean not found
————解决方式: 我是没添加spring-hibernate.jar
4、 Exception in thread "main" org.hibernate.PropertyAccessException: exception setting property value with CGLIB (set hibernate.cglib.use_reflection_optimizer=false for more info) setter of cn.com.entity.Emp.setComm
———基本类型的属性无法处理字段为null的情况
解决办法--改用相应的包装类(比如int-->java.lang.Integer) 难怪之前李老师对咱们说要咱们尽量将属性的类型定义为相应的包装类型。
问题描述:Null value was assigned to a property of primitive type setter ,hibernate long型数据无法读取 hiberante读long 整型数据出错 hiberante读数据库出错
解决办法:
javabean.hbm.xml
<property name="processInstanceId" type="java.lang.Long"/>
type="long" 改为
type="java.lang.Long"
private long 改为
private java.lang.Long processInstanceId;
原因:数据库字段值为NULL,long 类型不能赋值为NULL,只能为0,但有些实际应用中,如学生分数,0表示0分,NULL,则表示暂无分数所以,要不设数据字段不为NULL,要不就是用java.lang.Long.
如果映射时选择的是映射成 hibernate类型的话, 那么则配置文件中仍然是相应的基本类型, 只是在pojo类中配置成相应的包装类型即可。
5、Hibernate问题 flush-mode 一个事务中重复提交更新的SQL语句
问题现象:一个session开了事务,先执行insert、update,然后执行ICriteria.List()、
IQuery.List(),或者是某些session.Get()方法,最后ITransaction.Commit()。监控执行的SQL语句,
发现Hibernate重复执行了很多update的SQL操作。
问题原因:
a. flush-mode问题
NHibernate在执行ICriteria.List()、IQuery.List(),或者是session.Get()方法时,如果涉及到
了数据库某个表A,而当前session中存在这个表中的某个对象被修改了(dirty),则NHibernate在执行
查询前,根据flush-mode的设置,确定是否需要先将这些更新应用到数据库,然后再执行查询。
flush-mode的值:FlushMode.Auto,在查询前会先将当前session中dirty的对象应用到数据库,这也
是session对象的默认值;FlushMode.Commit,只有在执行ITransaction.Commit()的时候,才将当前
session中dirty的对象应用到数据库;FlushMode.Never,session中的所有对象的修改,任何时候都不
会提交数据库(包括ITransaction.Commit())。
设置方法,设置session对象的FlushMode这个属性。
对session的FlushMode需要谨慎设置,因为这是NHibernate保证数据一致性的方法之一,建议使用
Auto方式。
b. 自定义映射类型(IUserType)Equals方法的问题
在判断session中的对象是否为dirty,是否需要更新时,NHibernate将session中的每一个对象的每
一个属性,与该对象刚从数据库加载出来时的版本进行比较,检查是否相等。某个属性如果为自定义类
型(实现了IUserType登),不正确的Equals实现将导致NHibernate每次都认为这个对象是dirty的,所
以每次都会更新数据库。
因此,对自定义的属性类型,一定要重载Equals方法,正确的实现是否相等的判断逻辑。
首先,Hibernate session的FlushMode有如下几种:
FlushMode.ALWAYS;
FlushMode.AUTO;
FlushMode.COMMIT;
FlushMode.MANUAL;
FlushMode.NEVER;
可以通过session的setFlushMode来指定。
但是,如果使用spring+hibernate,并且不想在程序代码中通过setFlushMode来指定,而是想通过
spring的配置文件来指定,应该怎么指定?或者,可以通过spring的配置文件来指定吗?
现在的状况是:
aa: 在spring的 applicationContext.xml 中,
<bean id="txAttribute"
class="org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource">
<property name="properties">
<props>
<prop key="search">PROPAGATION_REQUIRED </prop>
</props>
</property>
</bean>
这样指定的话,在DAO Class中的get方法
public class BookInfoDaoImpl extends HibernateDaoSupport {
public List search(Object entity) {
Session session = SessionFactoryUtils.getSession(getHibernateTemplate
().getSessionFactory(),
getHibernateTemplate
().getEntityInterceptor(),
getHibernateTemplate
().getJdbcExceptionTranslator());
System.out.println("FlushMode:" + session.getFlushMode());
打印的结果是:
FlushMode:AUTO
bb: 如果在spring的 applicationContext.xml 中的配置更改为:
<prop key="search">PROPAGATION_REQUIRED,readOnly </prop>
打印的结果是:
FlushMode:NEVER
但我觉着FlushMode应该不是通过这样指定的,而且这样的话,除了Auto和Never以外的FlushMode没有办
法指定了
6 、 hibernate的配置文件属性:connection.autocommit=true有哪些缺点?为何不建议使用true呢????
这个属性是说,如果是true的话,就是自动提交,比如
在一个业务中中,你有多个操作数据库的子业务,
例如
业务SuperA中有子业务suba,subb,subc.....
如果是自动的话,
suba操作成功 提交
subb操作失败 回滚
subc操作失败 回滚
按照我们的逻辑当SuperA中有某一环节操作失败的话,都应该回滚到没有操作之前
而当为true时,则为出现a成功 b,c失败 ,SuperA不具备了时务的特征,原子性等等
当不是true时,这时事务的管理提交给了spring,Spring的事务控制是以一个bean为单位的,
SuperA是bean中一个方法或者其他,这样当执行事务SuperA时,只要a,b,c...中一个失败,都
会认定是失败操作 roolback. 这样避免了脏数据的出现,也合乎了事务的特征。。
1,和缓存没关系,当整合spring时,ORM一般都是hinernate,缓存级别都是在hibernate的xml文件
中设置的,一级缓存session,2级缓存sessionFactory,如果不是用orm,纯JDBC的话,缓存级别只能在
数据库端设置。所以与connection.autocommit= true无关。
我不知道为什么不建议使用true.官方有说明吗?
但是我分别说说使用true和不使用true的问题
(一)如果默认为true
1.保存对象是不需要开事务的,读写随意.
2.session.flush()是有意义的,因为session.flush()的操作是可以生效的.
(二)如果默认值为false
1.保存对象必须使用事务,不管是声明式事务还是编程式事务.当然也可以采用重置autocommit的方式
2.session.flush()是在事务块里面是没有意义的,因为数据操作是要统一提交的,但是这里我并没用经过
复杂的测试,稍后有时间我再尝试几种情况.
3.如果不在事务块内修改持久化对象后执行session.flush(),数据库会锁表.
总结:
session的autocommit模式也是可以修改的,所以默认为false,在复杂的情况下需要手工控制flush时可以
修改autocommit