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);

}

相关推荐