首页 > WEB开发 > 后台开发 > Spring框架整合篇
2014
10-05

Spring框架整合篇

11. 框架整合篇12

一、Spring整合JDBC开发(☆)

之所以在本节的标题上打了个☆,并不是因为Jdbc开发用的很广泛,而是整合Jdbc的过程有很多同整合Hibernate等ORM框架是类似的:

  • Spring容器向JdbcTemplate注入DataSource、向HibernateTemplate注入SessionFactory类似
  • 声明式事务处理一致
  • Spring提供的类的抽象一致

1、DataSource的配置与注入

本节以DBCP为例,讲解在Spring容器中配置DataSource,有关DBCP和DataSource的知识参考《数据库连接池(DataSource)》一文。

1)在IoC中配置DataSource

方式一:直接配置

<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_datasource"/>
   <property name="username" value="root"/>
   <property name="password" value=""/>
</bean>

方式二:使用属性占位符

--------------------------jdbc.properties--------------------------
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_datasource
jdbc.username=root
jdbc.password=
--------------------------applicationContext.xml--------------------------
<!-- 使用属性占位符进行配置(propertyPlaceHolder) -->
<!-- 引入jdbc.prperties配置文件 -->
<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>

2)Demo:DataSource的注入

① 定义Jdbc操作的模板类:JdbcTemplate(模仿了Spring,后面会涉及到该类),在该类中定义了一个insert方法。(还可以进行扩展,具体见Spring中的JdbcTemplate)

public class JdbcTemplate {
	private DataSource dataSource;

	public void setDataSource(DataSource dataSource) {
		this.dataSource = dataSource;
	}

	public void insert(String sql){
		try {
			Connection conn = dataSource.getConnection();
			Statement stmt = conn.createStatement();
			stmt.executeUpdate(sql);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

② PersonDaoImpl类继承了JdbcTemplate

public class PersonDaoImpl extends JdbcTemplate{

}

则PersonDaoImpl具有了JdbcTemplate中的ds属性和insert操作。

③ 在applicationContext.xml中配置personDao(两种方式)

------------------方式一------------------
<bean id="personDao" class="org.flyne.demo.PersonDaoImpl">
	<property name="dataSource" ref="dataSource" />
</bean>
------------------方式二------------------
<bean id="jdbcTemplate" class="org.flyne.demo.JdbcTemplate">
	<property name="dataSource" ref="dataSource" />
</bean>

<bean id="personDao" class="org.flyne.demo.PersonDaoImpl" parent="jdbcTemplate" />

④ 测试

@Test
public void testInsert() throws Exception{
	PersonDaoImpl personDao = (PersonDaoImpl)applicationContext.getBean("personDao");
	personDao.insert("insert into persons(name,age) values('flyne',24)");
}

说明:通过在Spring容器中配置数据源,在程序中就不需考虑DataSource的具体实现。

2、Spring对事务的支持

Spring框架对事务的支持是它的亮点之一。Spring的事务管理有如下优点:

  • 为复杂的事务API提供了一致的编程模型,如JTA、JDBC、Hibernate和JDO
  • 除了提供易于使用的编程式事务管理(不讨论),Spring还支持声明式事务管理(重点)。

1)一致的编程模型(事务管理器)

11. 框架整合篇3037

2)声明式事务管理Demo(☆)

业务场景:在PersonServiceImpl中定义了savePerson和getPersonById两个方法,其中savePerson要考虑事务事务,getPersonById不需要。要求用Spring提供的声明式事务管理来做。

① 在xml配置文件中引tx名称空间,并定义PlatformTransactionManager的bean。

<?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: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-2.5.xsd
     http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
     http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

</beans>

PlatformTransactionManager bean的定义如下(dataSource的配置参考上一节):

<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" ref="dataSource"/>
</bean>

② 配置事务:<tx:advice>标签

<tx:advice id="txAdvice" transaction-manager="txManager">
	<tx:attributes>
		<tx:method name="get*" read-only="true" propagation="NOT_SUPPORTED"/>
		<tx:method name="save*"/>
	</tx:attributes>
</tx:advice>

<aop:config>
	<aop:pointcut
			expression="execution(* org.flyne.service.impl.*.*(..))"
			id="perform"/>
	<aop:advisor advice-ref="txAdvice" pointcut-ref="perform"/>
</aop:config>

相关标签说明:

  • <tx:advice>:事务通知定义,其中”transaction-manager”属性指定事务管理器,并通过tx:attributes指定具体需要拦截的方法
  • <tx:method name=”save*”/>:表示将拦截以save开头的方法。该标签的属性有read-only、propagation。read-only设置事务的只读属性,true表示只读,如getXxx就使用的只读事务。propagation设置事务的传播属性,它是为了解决事务的嵌套问题,默认值为REQUIRED,getXxx设置为NOT_SUPPORTED,表示不需要事务支持。
  • <aop:advisor>:引用上面定义的事务通知。

③ 测试

在savePerson方法中保存两次,并在中间引入一个异常,则执行到1/0时事务就会回滚。

public void savePerson(Person person) {
	personDao.save(person);
	int i = 1/0;
	personDao.save(person);
}

3)Spring声明式事务管理的原理

11. 框架整合篇4982

3、Spring整合Jdbc

Spring中提供了JdbcTemplate类对Jdbc操作进行了封装,层次结构如下:

11. 框架整合篇5043

本文重点关注JdbcTemplate,JdbcDaoSupport的使用类似。JdbcTemplate只是对传统的Jdbc操作数据库的流程进行了封装(模板方法设计模式),在1.1节的Demo里也实现了一个简单的JdbcTemplate,使用时向其注入一个DataSource即可。

1)JdbcTemplate的使用:两种方式

方式一:继承JdbcTemplate

public PersonDaoImpl extends JdbcTemplate implements PersonDaoImpl{}

即1.1节Demo中的使用方式,在Spring容器中配置personDao时,也有两种方式:向PersonDaoImpl中注入DataSource或者继承jdbcTemplate。(见1.1节Demo)

方式二:让JdbcTemplate作为一个属性

public PersonDaoImpl implements PersonDao{
    private JdbcTemplate jdbcTemplate;
    public void setJdbcTemplate(JdbcTemplate jdbcTemplate){
        this.jdbcTemplate = jdbcTemplate;
    }
}

在Spring容器中配置personDao时,可以通过setter方法向其注入jdbcTemplate。

2)使用JdbcTemplate的Demo

① 定义PersonDaoImpl、PersonDaoImpl2,分别对应方式一和方式二

public class PersonDaoImpl extends JdbcTemplate{}

public class PersonDaoImpl2{
	private JdbcTemplate jdbcTemplate;

	public void setJdbcTemplate(JdbcTemplate jdbcTemplate){
		this.jdbcTemplate = jdbcTemplate;
	}

	public void execute(String sql){
		this.jdbcTemplate.execute(sql);
	}
}

② 在applicationContext.xml中进行配置

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
	<property name="dataSource" ref="dataSource" />
</bean>

<bean id="personDao" class="org.flyne.demo.PersonDaoImpl" parent="jdbcTemplate" />

<bean id="personDao2" class="org.flyne.demo.PersonDaoImpl2">
	<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean>

③ 测试:

public class PersonDaoImplTest {
	private static ApplicationContext applicationContext;
	@BeforeClass
	public static void init(){
		applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
	}

	@Test
	public void testPersonDaoImpl1() throws Exception{
		PersonDaoImpl personDao = (PersonDaoImpl)applicationContext.getBean("personDao");
		personDao.execute("insert into persons(name,age) values('flyne1',24)");
	}
	@Test
	public void testPersonDaoImpl2() throws Exception{
		PersonDaoImpl2 personDao = (PersonDaoImpl2)applicationContext.getBean("personDao2");
		personDao.execute("insert into persons(name,age) values('flyne2',24)");
	}
}

实际项目中单纯的使用Jdbc并不多,关于JdbcTemplate的使用就到这儿,更深入的了解还是看参考文档。

3)实际开发时到底选用JdbcTemplate还是JdbcDaoSupport?

说说博主个人观点:

  • Spring将JdbcDaoSupport设计成了抽象类,说明该类就是用来被继承用的。所以在用JDBC开发DAO层时,应该继承JdbcDaoSupport。
  • 把JdbcTemplate当成DAO中的一个属性也行啊?JdbcTemplate也是JdbcDaoSupport中的一个属性,所以还不如直接继承JdbcDaoSupport来得快。

综上,在写XxxDaoImpl时,应该继承JdbcDaoSupport,当然前提是使用Spring+Jdbc开发。


Spring框架整合篇》有 1 条评论

留下一个回复

你的email不会被公开。