2014-03-12 Spring的学习(4)------中间层数据访问(JDBC)
2014-03-12 Spring的学习(4)------中间层数据访问(JDBC)
查封炉台 发表于4年前
2014-03-12 Spring的学习(4)------中间层数据访问(JDBC)
  • 发表于 4年前
  • 阅读 330
  • 收藏 7
  • 点赞 0
  • 评论 0
摘要: Spring JDBC抽象框架所带来的价值将在以下几个方面得以体现:(注:使用了Spring JDBC抽象框架之后,应用开发人员只需要完成斜体字部分的编码工作。) 定义数据库连接参数 打开数据库连接 声明SQL语句 预编译并执行SQL语句 遍历查询结果(如果需要的话) 处理每一次遍历操作 处理抛出的任何异常 处理事务 关闭数据库连接 Spring将替我们完成所有使用JDBC API进行开发的单调乏味的、底层细节处理工作。

1.开发实验环境

   

导入相关开发库:
        aspectjrt.jar
	aspectjweaver.jar
	cglib-nodep-2.1_3.jar4
	common-annotations.jar
	commons-dbcp.jar
	commons-logging.jar
	commons-pool.jar
	dom4j-1.6.1.jar
	jaxen-1.1-beta-6.jar
	mysql-connector-java-5.0.8-bin.jar
	spring.jar

2.配置数据源

beans.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:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       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/aop 
       http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
      <context:property-placeholder location="classpath:jdbc.properties"/>
      <!-- commons-dbcp.jar  -->
      <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}" />
		
		<property name="initialSize" value="${jdbc.initialSize}" />
		<property name="maxActive" value="${jdbc.maxActive}" />
	
		<property name="maxIdle" value="${jdbc.maxIdle}" />
	
		<property name="minIdle" value="${jdbc.minIdle}" />
	  </bean>
	  <!-- 自动扫描cn.itcast包下的 所有Bean-->
	  <context:component-scan base-package="cn.itcast"/>
	  <!-- 依赖注入所有对象 -->
	  <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
	    <constructor-arg index="0" ref="dataSource"></constructor-arg>
	  </bean>
	  <context:annotation-config></context:annotation-config>
</beans>
jdbc.properties
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc\:mysql\://localhost\:3306/itcast?useUnicode\=true&amp;charsetEncoding\=UTF-8
jdbc.username=root
jdbc.password=lisai
jdbc.initialSize=1
jdbc.maxActive=500
jdbc.maxIdle=2
jdbc.minIdle=1
PersonDaoImpl.java
package cn.itcast.dao.impl;

import java.util.List;

import javax.annotation.Resource;


import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import cn.itcast.dao.PersonDao;
import cn.itcast.domain.Person;
@Transactional @Repository
public class PersonDaoImpl implements PersonDao {
	@Resource private JdbcTemplate jdbcTemplate;
	/* (non-Javadoc)
	 * @see cn.itcast.dao.impl.PersonDao#add(cn.itcast.domain.Person)
	 */
	public void add(Person person){
		jdbcTemplate.update("insert into tb_person(name) values(?) ", new Object[]{person.getName()}, new int[]{java.sql.Types.VARCHAR});
	}
	
	/* (non-Javadoc)
	 * @see cn.itcast.dao.impl.PersonDao#update(cn.itcast.domain.Person)
	 */
	public void update(Person person){
		jdbcTemplate.update("update tb_person set name = ? where id = ?  ", new Object[]{person.getName(),person.getId()}, new int[]{java.sql.Types.VARCHAR,java.sql.Types.INTEGER});
	}
	/* (non-Javadoc)
	 * @see cn.itcast.dao.impl.PersonDao#findByID(java.lang.Integer)
	 */
	public Person findByID(Integer id){
		return (Person) jdbcTemplate.queryForObject("select id,name from tb_person where id=?", new Object[]{id},new int[]{java.sql.Types.INTEGER},new PersonRowMapper());
	}
	/* (non-Javadoc)
	 * @see cn.itcast.dao.impl.PersonDao#findAll()
	 */
	@SuppressWarnings("unchecked")
	public List<Person> findAll(){
		return (List<Person>)jdbcTemplate.query("select id,name from tb_person",new PersonRowMapper());
		
	}
	/* (non-Javadoc)
	 * @see cn.itcast.dao.impl.PersonDao#delete(java.lang.Integer)
	 */
	public void delete(Integer id){
		jdbcTemplate.update("delete from tb_person where id = ? ", new Object[]{id}, new int[]{java.sql.Types.INTEGER});
	}
}
PersonRowMapper.java
package cn.itcast.dao.impl;

import java.sql.ResultSet;
import java.sql.SQLException;

import org.springframework.jdbc.core.RowMapper;

import cn.itcast.domain.Person;

public class PersonRowMapper implements RowMapper {

	public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
		Person person = new Person();
		person.setId(rs.getInt("id"));
		person.setName(rs.getString("name"));
		return person;
	}

}
Person.java
package cn.itcast.domain;


public class Person {
	private Integer id;
	private String name;
	public Person(String name){
		this.name = name;
	}
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Person() {
		super();
		// TODO Auto-generated constructor stub
	}
	public Person(Integer id, String name) {
		super();
		this.id = id;
		this.name = name;
	}
}
CREATE TABLE tb_person (
  id int(12) NOT NULL auto_increment,
  name varchar(20) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
测试代码:JdbcSpringTest.java
package junit.test;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import cn.itcast.dao.PersonDao;
import cn.itcast.domain.Person;

public class JdbcSpringTest {

	private static PersonDao personDao;
	@BeforeClass
	public static void setUpBeforeClass() throws Exception{
		ApplicationContext ctx=new ClassPathXmlApplicationContext("beans.xml");
		personDao=(PersonDao) ctx.getBean("personDaoImpl");
	}
	@Test
	public void testAdd() {
		personDao.add(new Person("mmmn"));
		System.out.println("OK");
	}

	@Test
	public void testUpdate() {
		Person person = new Person(4, "token");
		personDao.update(person);
		System.out.println("Ok");
	}

	@Test
	public void testFindByID() {
		System.out.println(personDao.findByID(4).getName());
	}

	@Test
	public void testFindAll() {
		for(Person person:personDao.findAll()){
			System.out.println(person.getName());
		}
	}

	@Test
	public void testDelete() {
		personDao.delete(4);
	}
}
测试结果:通过查看数据库数据结果一致.
//~

3.注解方式配置事务

a. beans.xml的修改
 <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	     <property name="dataSource" ref="dataSource"></property>
</bean>
b. 引入事务管理的命名空间
      xmlns:tx="http://www.springframework.org/schema/tx"
      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
c. 采用注解方式@Transactional
      <tx:annotation-driven transaction-manager="txManager"/>
      @Transactional 注解是用来指定接口、类或方法必须拥有事务语义的元数据。 如:“当一个方法开始调用时就开启一个新的只读事务,并停止掉任何现存的事务”。
             默认的 @Transactional 设置如下: 
	     事务传播设置是 PROPAGATION_REQUIRED
	     事务隔离级别是 ISOLATION_DEFAULT
	     事务是 读/写
	     事务超时默认是依赖于事务系统的,或者事务超时没有被支持。
	     任何 RuntimeException 将触发事务回滚,但是任何 checked Exception 将不触发事务回滚

4.声明实事务管理(基于XML配置文件)

<!-- 开启事务 -->
<aop:config>
     <aop:pointcut expression="execution(* cn.itcast.dao..*.*(..))" id="transactionPointcut"/>
     <aop:advisor advice-ref="txAdvice" pointcut-ref="transactionPointcut"/>
</aop:config>
<tx:advice id="txAdvice" transaction-manager="txManager">
	<tx:attributes>
	      <tx:method name="*" read-only="true" propagation="NOT_SUPPORTED"/>
	</tx:attributes>
</tx:advice>
Spring的声明式事务管理是通过Spring AOP实现的,因为事务方面的代码与Spring绑定并以一种样板式风格使用, 不过尽管如此,你一般并不需要理解AOP概念就可以有效地使用Spirng的声明式事务管理。
从考虑EJB CMT和Spring声明式事务管理的相似以及不同之处出发是很有益的。它们的基本方法是相似的: 都可以指定事务管理到单独的方法;如果需要可以在事务上下文调用 setRollbackOnly() 方法。不同之处在于:
不像EJB CMT绑定在JTA上,Spring声明式事务管理可以在任何环境下使用。只需更改配置文件, 它就可以和JDBC、JDO、Hibernate或其他的事务机制一起工作。
Spring的声明式事务管理可以被应用到任何类(以及那个类的实例)上,不仅仅是像EJB那样的特殊类。
Spring提供了声明式的 回滚规则:EJB没有对应的特性,我们将在下面讨论。回滚可以声明式的控制,不仅仅是编程式的。
Spring允许你通过AOP定制事务行为。例如,如果需要,你可以在事务回滚中插入定制的行为。 你也可以增加任意的通知,就象事务通知一样。使用EJB CMT,除了使用setRollbackOnly(),你没有办法能够影响容器的事务管理。
Spring不提供高端应用服务器提供的跨越远程调用的事务上下文传播。如果你需要这些特性,我们推荐你使用EJB。 然而,不要轻易使用这些特性。因为通常我们并不希望事务跨越远程调用。
TransactionProxyFactoryBean在哪儿?
Spring2.0及以后的版本中声明式事务的配置与之前的版本有相当大的不同。主要差异在于不再需要配置TransactionProxyFactoryBean了。
Spring2.0之前的旧版本风格的配置仍然是有效的;你可以简单地认为新的<tx:tags/>替你定义了TransactionProxyFactoryBean。
回滚规则的概念比较重要:它使我们能够指定什么样的异常(和throwable)将导致自动回滚。我们在配置文件中声明式地指定,无须在Java代码中。同时,我们仍旧可以通过调用 TransactionStatus 的 setRollbackOnly() 方法编程式地回滚当前事务。通常,我们定义一条规则, 声明 MyApplicationException 必须总是导致事务回滚。 这种方式带来了显著的好处,它使你的业务对象不必依赖于事务设施。典型的例子是你不必在代码中导入Spring API,事务等。

对EJB来说,默认的行为是EJB容器在遇到 系统异常(通常指运行时异常)时自动回滚当前事务。 EJB CMT遇到 应用异常(例如,除了 java.rmi.RemoteException 外别的checked exception)时并不会自动回滚。 默认式Spring处理声明式事务管理的规则遵守EJB习惯(只在遇到unchecked exceptions时自动回滚),但通常定制这条规则会更有用。
end.......


共有 人打赏支持
粉丝 49
博文 56
码字总数 138491
×
查封炉台
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: