spring整合hibernate
来自:http://hi.baidu.com/%BB%A8%BB%F0%C8%D5%BC%C7/blog/item/9f4e9325b7384c6e34a80fa3.html
二、spring整合hibernate
1.查看applicationContext.xml有了变化,多了hibernate的配置
2.建立表的映射
选择数据库视图,accp数据库
生成users.hbm.xml与Users.java
去掉catagory属性,否则会报错
也在applicationContext.xml中增加了映射
3.整合hibernate有两种方式
4.第一种方式,继承
org.springframework.orm.hibernate3.HibernateTemplate,该类是spring封装了操作Hibernate的实现细节的类,用于代替Session的相关操作。主要方法:
Serializablesave(Object?entity):保存记录
voidupdate(Object?entity):修改记录
voiddelete(Object?entity):删除记录
Objectget(Class?entityClass,Serializable?id)
Objectload(Class?entityClass,Serializable?id)
ListexecuteFind(HibernateCallback?action):查询,返回集合
Objectexecute(HibernateCallback?action):查询,返回对象
总的说来,该类的方法和Session接口中定义的方法是一致的.
1)在dao包中写接口IDao,
publicinterfaceIDao{
publicvoidsave(Usersu);
publicListgetAll();
publicbooleanvalidate(Usersu);
}
UserDaoextendsHibernateDaoSupportimplementsIDao
publicclassUserDaoextendsHibernateDaoSupportimplementsIDao{
publicvoidsave(Usersu){
this.getHibernateTemplate().save(u);
}
}
2)在spring中配置UserDao,从哪取连接,property二择其一
给继承了HibernateDaoSupport的对象我们注入一个sessionFactory对象也可以,他会自动生成一个hibernateTemplate对象
<beanid="userdao"class="org.accp.hibernate.dao.UserDao">
<propertyname="sessionFactory"ref="sessionFactory"/>
<!--<propertyname="hibernateTemplate"ref="hibernateTemplate"/>-->
</bean>
3)测试
导入mysql.jar,不能拷贝到lib下,也找不到,这时要在buildPath中导入外部jar
去掉users.hbm.xml中的catagory属性,否则会报错
\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ApplicationContextac=newClassPathXmlApplicationContext("applicationContext.xml");
IDaodele=(IDao)ac.getBean("userdao");
Usersu=newUsers();
u.setUid("userdao");
u.setPwd("123");
u.setVersion(2);
dele.save(u);
5.第二种方式
1)新建一个类UserDao2,加一成员变量HibernateTemplate
加一构造函数,注入sessionFactory
加一setter方法,注入sessionFactory
publicclassUserDao2implementsIDao{
privateHibernateTemplatehibernateTemplate;
publicUserDao2(HibernateTemplatehibernateTemplate){
this.hibernateTemplate=hibernateTemplate;
}
publicvoidsave(Usersu){
hibernateTemplate.save(u);
}
}
2)改配置文件applicationContext.xml
<beanid="userdao2"class="org.accp.hibernate.dao.UserDao2">
<constructor-arg>
<refbean="hibernateTemplate"/>
</constructor-arg>
</bean>
<beanid="hibernateTemplate"class="org.springframework.orm.hibernate3.HibernateTemplate">
<propertyname="sessionFactory">
<refbean="sessionFactory"/>
</property>
</bean>
6.HibernateDaoSupport与连接的管理
而调用getHibernateTemplate()就会自动关闭连接。
这是日志
[main]DEBUGorg.springframework.orm.hibernate3.SessionFactoryUtils-ClosingHibernateSession
自动关闭连接会造成延迟加载初始化异常,此时可用OpenSessionInView模式解决。Spring提供OpenSessionInView来解决这个问题,有两种方式。
1)Interceptor,在applicationContext.xml配置
<beanid="openSessionInViewInterceptor"class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
<propertyname="sessionFactory"ref="sessionFactory"/>
</bean>
<beanid="urlMapping"class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<propertyname="interceptors"ref="openSessionInViewInterceptor"/>
<propertyname="mappings">
<props>
......
</props>
</property>
</bean>
2)Filter,在web.xml中配置
<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
<!--默认情况下,这个Filter会在Spring的bean池中找一个叫做sessionFactory的bean。如果使用了其他名字的SessionFactory,则应该在这里-->
<init-param>
<param-name>sessionFactoryBeanName</param-name>
<param-value>sessionFactory</param-value>
</init-param>
<!--singleSession默认为true,若设为false则等于没用OpenSessionInView-->
<init-param>
<param-name>singleSession</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
加了这个配置,就要加监听器和初始文件的参数,否则报错
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
7.HibernateDaoSupport与自动提交
每执行一个sql,默认都是由spring自动提交事务。可以在数据源中插入进去
<propertyname="defaultAutoCommit">
<value>false</value>
</property>
8.spring整合hibernate事务
Don'tcallme,Iwillcallyou
更少代码,更少BUG
Spring提供的事务管理可以分为两类:编程式的和声明式的。
1)编程式的
比较灵活,但是代码量大,存在重复的代码比较多,当你只有很少的事务操作时,编程式事务管理通常比较合适。
代码
publicclassUserDao3extendsHibernateDaoSupportimplementsIDao{
privateHibernateTransactionManagertransactionManager;
publicvoidsetTransactionManager(HibernateTransactionManagertransactionManager){
this.transactionManager=transactionManager;
}
publicvoidsave(Usersu){
DefaultTransactionDefinitiondef=newDefaultTransactionDefinition();
TransactionStatusstatus=transactionManager.getTransaction(def);
try{
this.getHibernateTemplate().save(u);
//不提交插入不了
transactionManager.commit(status);
}catch(Exceptione){
transactionManager.rollback(status);
}
}
}
配置
<beanid="userdao3"class="org.accp.hibernate.dao.UserDao3">
<propertyname="sessionFactory"ref="sessionFactory"/>
<propertyname="transactionManager"ref="transactionManager"/>
</bean>
<beanid="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<propertyname="sessionFactory">
<refbean="sessionFactory"/>
</property>
</bean>
2)声明式的
其DAO必须要有接口,否则声明式事务就会报错。
a)事务属性
<propkey="save*">PROPAGATION_REQUIRED,readOnly</prop>
key属性确定代理应该给哪个方法增加事务行为。PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED--如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。
事务属性中的readOnly标志表示对应的事务应该被最优化为只读事务,避免dirtychecking。
b)事务策略
为了实际执行事务,Spring所有的事务划分功能都通过传递适当的TransactionDefinition实例,委托给PlatformTransactionManager。
Spring具有多种PlatformTransactionManager实现,它们分为两类:
局部事务策略--针对单个资源执行事务(在多数情况下是针对单个的数据库)。
全局事务管理--执行有可能跨越多个资源的全局事务。
c)事务代理
TransactionProxyFactoryBean是Spring2.0之前的旧版本风格的配置
TransactionInterceptor,它使用一个PlatformTransactionManager实现配合,在方法调用前后实施事务。
d)例子
配置文件
<beanid="userdao4"class="org.accp.hibernate.dao.UserDao4">
<propertyname="sessionFactory"ref="sessionFactory"></property>
</bean>
<beanid="proxyTemplate"class="org.springframework.transaction.interceptor.TransactionInterceptor">
<propertyname="transactionManager">
<refbean="transactionManager"/>
</property>
<propertyname="transactionAttributes">
<props>
<propkey="save*">PROPAGATION_REQUIRED</prop>
<propkey="query*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
<beanid="nameproxy"class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<propertyname="beanNames">
<list><value>userdao4</value></list>
</property>
<propertyname="interceptorNames">
<list>
<value>proxyTemplate</value>
</list>
</property>
</bean>
不用事务,即使报错也始终能插入进去一条。用了事务,一报错则一条都不进去。
配置完成前,将defaultAutoCommit设成false后,始终插入不进去。
配置完成后,将使用声明式事务能插入进去了。
9.sql提高,修改UserDao
//executeFind返回集合
publicListquery(){
returnthis.getHibernateTemplate().executeFind(newHibernateCallback(){
publicObjectdoInHibernate(Sessionsession)throwsHibernateException,
SQLException{
returnsession.createQuery(
"from"+cls.getName()+"asaorderbya.uiddesc").list();
}
});
}
//execute返回对象
publicbooleanvalidate(finalUsersu){
Listls=(List)this.getHibernateTemplate().execute(
newHibernateCallback(){
publicObjectdoInHibernate(Sessionsession)
throwsHibernateException,SQLException{
Queryqy=session
.createQuery("fromUsersuwhereu.uid=:uidandu.pwd=:pwd");
qy.setString("uid",u.getUid());
qy.setString("pwd",u.getPwd());
Listli=qy.list();
returnli;
}
});
return(ls.size()>0);
}