6.spring持久化相关

        Spring在持久化上做出了一个统一的模型,目的是为了简化持久化的开发,使得数据访问层和持久化方案的选择相互独立。

        统一了数据访问异常:

传统的JDBC异常分类比较薄弱,并且都为检查型异常,在程序员对数据库的操作过程中,需要强制的去捕获SQLException,第一是工作比较繁琐,第二个就算捕获了之后其实际意义也不大,并且SQLException包含的异常问题不能够准确的进行表达,有可能是连接异常,有可能是数据访问的其他问题,spring在此基础上统一了数据访问异常,提供更加丰富的异常管理,并且所有异常都会运行期异常,不需要用户做出捕获动作,需要进行捕获时,由程序员自行决定,无论是选择何种持久化方案,在spring的管理下,异常都可以得到统一,这样从异常的角度完成了数据访问层和持久化方案选择的独立。

        数据访问模板:

spring提供数据访问模板,利用模板方法模式以及回调来简化数据访问层的代码编写,使得程序员在数据访问代码编写时候,关注点只关注数据访问的核心逻辑,对于连接的打开,关闭等操作都进行了忽略,大大的加快了数据访问的开发效率,也就是说spring提供模板,减少了系统当中的样板代码的编写

常用的模板:

模板类用途
jca.cci.core.CciTemplateJCA CCI连接
jdbc.core.JdbcTemplateJDBC连接
jdbc.core.namedparam.NamedParameterJdbcTemplate支持命名参数的Jdbc连接
jdbc.core.simple.SimpleJdbcTemplate通过Java 5简化后的JDBC连接
orm.hibernate.HibernateTemplatehibernate2.x session
orm.hibernate3.HibernateTemplatehibernate3.x session
orm.ibatis.SqlMapClientTemplateibatis sqlMap客户端
orm.jdo.jdoTemplateJava数据对象实现
orm.jpa.jpaTemplateJava持久化API管理器

 

        提供DAO支持类:

DAO支持类与spring提供的模板如出一辙,如果要使用模板,则可以继承于spring DAO的支持类,之后很方便的获取到DAO支持类提供的模板,进行数据访问操作。上述模板介绍中每一个模板都对应一个DAO支持类,用于更为方便的在spring中获取到模板。

 

配置数据源:

在spring配置数据源有三种方式:

通过JDBC驱动定义的数据源
JNDI查找数据源
连接池的数据源

JDNI数据源:

增加命名空间:

xmlns:jee="http://www.springframework.org/schema/jee"

 

xsi:schemaLocation="http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-3.0.xsd"

 XML配置:

<jee:jndi-lookup jndi-name="jdbc/DS" resource-ref="true" />

 jndi-name用于指定JNDI查找路径,如果是在JAVA应用服务器中需要配置resource-ref为true,这样会自动添加上java:comp/env/前缀

 

数据库连接池:

数据库连接池的选择很多,通常会有prooxy,c3p9,dbcp等等,spring本身没有提高数据库连接池的实现,但是可以有效的与第三方数据库连接池进行集成

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
  <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
  <property name="url" value="jdbc:mysql://localhost:3306/hello?useUnicode=true&amp;charact   erEncoding=utf8"></property>
  <property name="username" value="root"></property>
  <property name="password" value="root"></property>
  <property name="initialSize" value="5"></property>
  <property name="maxActive" value="10"></property>
</bean>

 

基于JDBC驱动的数据源:

spring提供了两个最简单的JDBC数据源:

DriverMangerDatasource:每个连接请求返回一个新建的连接,但是没有池化管理

SingleConnectionDatasource:每次返回都用同一个连接

应用一个连接的SingleConnectionDatasource不适用于多线程的应用程序,而每次请求都会创建的DriverManager会在程序运行中出现性能问题,所以强烈建议在生产环境中使用数据库连接池

<bean id="dataSource2" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
  <property name="url" value="jdbc:mysql://localhost:3306/hello?useUnicode=true&amp;charact   erEncoding=utf8"></property>
  <property name="username" value="root"></property>
  <property name="password" value="root"></property>
</bean>

 

在Spring中使用JDBC:

spring提供三种JdbcTemplate用于对JDBC的访问,JdbcTemplate,SimpleJdbcTemplate,NamedParameterJdbcTemplate,其中SimpleteJdbcTemplate在3.1中已经被废弃,原因是JdbcDaoSupport 或NamedParameterJdbcDaoSupport已经提供了其所有功能,所以要使用SimpleJdbcTemplate继承于JdbcDaoSupport即可

JdbcTemplate:最基本的Jdbc模板,提供基本的数据库访问

SimpleJdbcTemplate:利用java 5的一些特性,如自动装箱,泛型,以及可变参数来简化JDBC模板使用

NamedParameterJdbcTemplate:查询时候,可以使用命名参数绑定到sql中,而不是只是简单的索引参数

 

JdbcTemplate配置:

 

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

 

 

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate">
  <constructor-arg ref="dataSource"></constructor-arg>
</bean>
  NamedParameterJdbcTemplate配置:

 

 

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.namedparam.NamedParameterJdbcT  emplate">
  <constructor-arg ref="dataSource" ></constructor-arg>
</bean>
 使用:

 

 

public void addBand(Band band){
  String sql = "insert into t_band(id, name), values(?,?)";
  getJdbcTemplate().update(sql, band.getId(), band.getName());
}
 
public Band findBandById(String id){
	String sql = "select id,name from t_band where id = ?";
	return getJdbcTemplate().queryForObject(sql, new ParameterizedRowMapper<Band>() {
		@Override
		public Band mapRow(ResultSet rs, int rowNum) throws SQLException {
			Band band = new Band();
			band.setId(rs.getString(1));
			band.setName(rs.getString(2));
			return band;
		}
	}, id);
}
 有命名参数绑定的sql,使用NamedParameterJdbcTemplate,该例中JdbcTemplate来自于NamedParameterJdbcDaoSupport:

 

 

public Band findBandById(String id){
	String sql = "select id,name from t_band where id = :id";
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("id", id);
	return getJdbcTemplate().queryForObject(sql, new ParameterizedRowMapper<Band>() {
		@Override
		public Band mapRow(ResultSet rs, int rowNum) throws SQLException {
			Band band = new Band();
			band.setId(rs.getString(1));
			band.setName(rs.getString(2));
			return band;
		}
	}, params);
}
 

 

Spring集成HIbernate:

LocationSessionFactory(hibernate4)的配置:

 

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
	<property name="dataSource" ref="dataSource"></property>
	<property name="mappingResources">
		<list>
			<value>band.hbm.xml</value>
		</list>
	</property>
	<property name="hibernateProperties">
		<props>
			<prop key="dialect">org.hibernate.dialect.MySQL5Dialect</prop>
		</props>
	</property>
</bean>

 基于注解扫描@Entity

 

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
	<property name="dataSource" ref="dataSource"></property>
	<property name="packagesToScan" value="org.robbie.test"></property>
	<property name="hibernateProperties">
		<props>
			<prop key="dialect">org.hibernate.dialect.MySQL5Dialect</prop>
		</props>
	</property>
</bean>

 

 在Spring中使用hibernate:

 

package org.robbie.test.spring.beans;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

@Repository
public class MyDao{
	
	@Autowired
	private SessionFactory sessionFactory;
	
	private Session getCurrentSession(){
		return sessionFactory.openSession();
	}
	
	public void insert(){
		Session session = getCurrentSession();
		Transaction transaction = session.getTransaction();
		transaction.begin();
		try {
			MyDomain domain = new MyDomain();
			domain.setId("4");
			domain.setName("robbie");
			session.save(domain);
		} catch (Exception e) {
			transaction.rollback();
			System.out.println(e);
		}
		transaction.commit();
	}

}

 通过注入的方式,把SessionFactory装配进来,调用API进行使用,类级别的注解@Repository有两个作用,第一个作用是作为Spring的组件使用,会被自动检测到容器当中,第二个是如果配置了spring全局异常处理,那么在标注了该注解的类中的方法都会捕获sql异常,并统一转换成与持久化方案无关的spring数据访问异常(运行期异常),使得DAO和持久化选择方式脱离,程序更容易管理,并减少代码量。

Spring统一持久层异常的配置:

 

<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />

 如果是hibernate4还需要加入以下配置(在JTA事务中):

<bean class="org.springframework.orm.hibernate4.HibernateExceptionTranslator"/>

 

 

 

Spring集成JPA:

 JPA的实体管理工厂有两个:

LocalEntityManagerFactoryBean:是应用程序管理类型的工厂,一般会在一个独立的应用程序中使用

Local,由用户程序直接请求工厂,创建实体管理器,需要手动打开或关闭事务,单独进行配置

LocalContainerManagerFactoryBean:是容器管理类型的工厂,用户程序不会直接跟此工厂打交道,而是通过容器进行注入,创建实体管理器,事务受容器管理,在spring中进行配置

 

应用程序管理类型的工厂配置:

创建persistence.xml,这个文件必须位于类路径的META-INF目录下

 

<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
	<persistence-unit name="unit1">
		<class>org.test.Bean1</class>
		<class>org.test.Bean2</class>
		<properties>
			<property name="toplink.jdbc.driver" value="org.hsqldb.jdbcDriver"></property>
			<property name="toplink.jdbc.url" value="jdbc:hsqldb:hsql://localhost/test"></property>
			<property name="toplink.jdbc.user">root</property>
			<property name="toplink.jdbc.password">root</property>
		</properties>
	</persistence-unit>
</persistence>
 增加spring的配置:

 

 

<bean id="emf" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
	<property name="persistenceUnitName" value="unit1"></property>
</bean>
 目前为止JPA的配置没有完成,是因为没有配置实现,但是把相关的JPA实现配置信息全部放在persistent.xml上会显得非常的臃肿和不好管理,所以通常情况下在web项目都没有采用这种方式的配置。

 

 

在容器管理的实体管理器工厂:

 

<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
	<property name="dataSource" ref="dataSource"></property>
	<property name="jpaVendorAdapter" ref="jpaVendorAdapter"></property>
</bean>

<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
	<property name="database" value="MYSQL"></property>
	<property name="showSql" value="true"></property>
	<property name="generateDdl" value="true"></property>
	<property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect"></property>
</bean>
 JPA的厂商适配器:
EclipseLinkJpaVendorAdapter
HibernateJpaVendorAdapter
OpenJapVendorAdaptor
ToplinkJpaVendorAdaptor

 

从JNDI获取实体管理器工厂:

 

<jee:jndi-lookup id="emf" jndi-name="persistence/unit1" />
 

 

编写基于JPA的DAO:

@PersistenceContext
private EntityManager em;

 需要用到em的地方通过此种方法进行注入即可。

 

目前为止,与持久化框架的集成都是采用传统的XML配置,回顾基于JAVA的@Configuration配置,也可以完成,并且更加灵活,至于项目中该采用何种配置方法由用户自己决定。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值