注:本文中所用Spring版本为spring-framework-3.2.3.RELEASE
今天给大家介绍一下spring整合hierbnate的过程,文章内容由以下部分组成:
1.通过spring指定Datasource
2.通过spring注入sessionFactory
3.通过spring实现声明式事务管理
通过spring指定Datasource
对于Datasource的概念,想必大家都熟悉了,如果仍不熟悉Datasource概念,请读者查阅相关资料,此处只做简单介绍,所谓Datasource,从字面上看很简单,就是数据源的意思,也就是指定我的数据库在哪,是哪种数据库,以及连接的一些参数。
在spring中配置Datasource有三种方式,分别是:
i. c3p0
ii. dbcp
iii. proxool
今天我们讲述的是第二种,dbcp。
笔者认为,技术学习特别是计算机技术的学习的本质是掌握学习方法,因为计算机技术日新月异,只是满足于掌握某种技术或者是某个知识点,显然跟不上IT技术的快速变化,所以唯有掌握学习方法,才能以不变应万变。
我们先从网上下载spring-framework-3.2.3.RELEASE版本(spring官网:http://www.springsource.org)。
首先打开下载好的spring-framework-3.2.3.RELEASE的文件夹,spring既然支持以dbcp的方式配置Datasource,那么在它的reference文档中肯定有关于怎么配置的说明,甚至对于spring这么先进成熟的框架而言,应该会有个小例子,所以我们首先打开spring的reference文档。
打开spring的reference文档后,进行关键词搜索:dbcp,当我们找到第六项匹配的时候,基本上就找到了配置例子了,文档中是这么写的:
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<!-- results in a setDriverClassName(String) call -->
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
<property name="username" value="root"/>
<property name="password" value="masterkaoli"/>
</bean>
我们只需将其中的参数换成我们自己的参数即可:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<!-- 对于数据源的参数配置 -->
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/spring"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
其实我们仔细看一下发现它还介绍了另外一种配置方法:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" value="classpath:com/foo/jdbc.properties"/>
</bean>
<bean id="dataSource" destroy-method="close"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
以上就是使用Placeholder先指定一个properties类型的配置文件,然后再定义一个Datasource,其中的参数都是以变量的名称从properties配置文件中读取
以上就是spring中配置Datasource的方法了,很简单,其实凡是关于spring的各种配置在spring的reference文档中都有说明,而且基本上都是有小例子供你参考的,所以有什么配置不知道怎么配的时候一定要先查看spring的reference文档
我们用个小实例来实际检验一下刚才我们的配置是否正确,实例工程见http://download.csdn.net/detail/qinwu19910928/5567751:(spring配置Datasource需要引用两个jar包:commons-dbcp.jar和commons-pool.jar)
以下是连接数据库的类的代码:
package com.spring.dao.impl;
import java.sql.Connection;
import java.sql.SQLException;
import javax.annotation.Resource;
import javax.sql.DataSource;
import org.springframework.stereotype.Component;
import com.spring.model.User;
import com.spring.dao.UserDAO;
@Component("userDAO")
public class UserDAOImpl implements UserDAO {
private DataSource dataSource;
private Connection connection;
public DataSource getDataSource() {
return dataSource;
}
@Resource
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}
public void save(User user) {
try {
connection = dataSource.getConnection();
connection.createStatement().executeUpdate(
"insert into user values (null,'xiaohei')");
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
以上即是在spring中配置Datasource的过程。
通过spring注入sessionFactory
接下来介绍下怎么在spring中注入Hibernate的sessionFactory,实现利用spring来管理Hibernate的sessionFactory,既然是spring支持的配置,同样在spring的reference文档中肯定也会有说明,如下就是spring的reference文档给出的例子。
<beans>
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
<property name="url" value="jdbc:hsqldb:hsql://localhost:9001"/>
<property name="username" value="sa"/>
<property name="password" value=""/> </bean>
<bean id="mySessionFactory"class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource"/>
<property name="mappingResources">
<list>
<value>product.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.HSQLDialect
</value>
</property>
</bean>
</beans>
从中可看出,此时Hibernate是使用xml方式标注实体类的,如果使用注解方式标注实体类,标红处的配置是不一样的(具体区别读者可上网查一下),而且这是针对Hibernate3的配置,因为本文使用的hibernate版本是hibernate-release-4.2.2.Final,对于Hibernate4.x来说,不管是xml方式还是注解方式,对注入sessionFactory的配置中class属性的配置都一样的,都是
<bean id="mySessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
这一点读者需注意,到此为止我们就把hibernate的sessionFactory交给spring管理了,这样我们使用hibernate访问数据库的时候,就可以向下面这样了
package com.spring.dao.impl;
import javax.annotation.Resource;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.stereotype.Component;
import com.spring.dao.UserDAO;
import com.spring.model.User;
@Component("userDAO")
public class UserDAOImpl implements UserDAO {
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
return sessionFactory;
}
@Resource
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public void save(User user) {
Session s = sessionFactory.openSession();
s.beginTransaction();
s.save(user);
s.getTransaction().commit();
}
}
实例工程见http://download.csdn.net/detail/qinwu19910928/5569841
通过spring实现声明式事务管理
先来介绍下annotation注解方式声明事务的配置方法,同样在spring的reference文档中也都有说明,读者可自己查阅,我们直接来看下我们实例工程中的xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<context:annotation-config />
<context:component-scan base-package="com.spring" />
<!-- 配置Datasource -->
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<value>classpath:jdbc.properties</value>
</property>
</bean>
<bean id="dataSource" destroy-method="close"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName"
value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<!-- 配置sessionFactory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<!-- 将dataSource注入给sessionFactory -->
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.spring.model.User</value>
<value>com.spring.model.Log</value>
</list>
</property>
<!-- 配置Hibernate的一些属性 -->
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<!-- 声明事务管理器,将我们定义的sessionFactory注入 -->
<bean id="txManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- 声明是annotation驱动的事务管理,指定我们自己配置的事务管理器txManager -->
<tx:annotation-driven transaction-manager="txManager"/>
</beans>
而在需要声明事务的方法上面只要加上@Transactional就万事大吉了,如下所示:
package com.spring.service;
import javax.annotation.Resource;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import com.spring.dao.LogDAO;
import com.spring.model.Log;
import com.spring.dao.UserDAO;
import com.spring.model.User;
@Component("userService")
public class UserService {
private UserDAO userDAO;
private LogDAO logDAO;
@Transactional
public void add(User user) {
userDAO.save(user);
Log log = new Log();
log.setMsg("a user saved!");
logDAO.save(log);
}
public UserDAO getUserDAO() {
return userDAO;
}
@Resource(name = "userDAO")
public void setUserDAO(UserDAO userDAO) {
this.userDAO = userDAO;
}
public LogDAO getLogDAO() {
return logDAO;
}
@Resource
public void setLogDAO(LogDAO logDAO) {
this.logDAO = logDAO;
}
}
这样我们,就把事务完全交给spring来管理了,当UserService中的add方法抛出RuntimeException时,spring就会帮我们自动回滚。
实例工程:http://download.csdn.net/detail/qinwu19910928/5575183
下面我们再来介绍下xml方式管理事务,配置文件如下
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<context:annotation-config />
<context:component-scan base-package="com.spring" />
<!-- 配置Datasource -->
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<value>classpath:jdbc.properties</value>
</property>
</bean>
<bean id="dataSource" destroy-method="close"
class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName"
value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<!-- 配置sessionFactory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<!-- 将dataSource注入给sessionFactory -->
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.spring.model.User</value>
<value>com.spring.model.Log</value>
</list>
</property>
<!-- 配置Hibernate的一些属性 -->
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<!-- 声明事务管理器,将我们定义的sessionFactory注入 -->
<bean id="txManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- aop指定好切面,指定切面逻辑为txAdvice -->
<aop:config>
<aop:pointcut id="bussinessService"
expression="execution(public * com.spring.service..*.*(..))" />
<aop:advisor pointcut-ref="bussinessService"
advice-ref="txAdvice" />
</aop:config>
<!-- 在切面逻辑中指定事务管理器为txManager -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="add*"/>
</tx:attributes>
</tx:advice>
</beans>
上面的配置文件中用到了spring的aop的配置,读者对这一部分不理解的请先学习spring的aop特性然后再回来看这个配置。
而在java代码中只要把原来的@Transaction注解去掉就可以了
实例工程:http://download.csdn.net/detail/qinwu19910928/5575359