Spring 配置詳解

spring4配置文件詳解

 

1、配置數據源

基本的加載properties配置文件java

<context:property-placeholder location="classpath*:/appConfig.properties" />mysql

 

一、JNDI方式

<jee:jndi-lookup id="dataSource" jndi-name="/jdbc/mysqlDS" resource-ref="true"/>spring

l  jndi-name:指定JNDI中資源名稱sql

l  resource-ref:若是應用程序運行在java應用程序服務器中,值設爲true,這樣jndi-name會自動加上java:comp/env/前綴數據庫

 

二、數據鏈接池方式

DBCP鏈接池:

使用:org.apache.commons.dbcp.BasicDataSource進行配置apache

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">緩存

   <!-- 【必須】  數據庫驅動-->安全

   <property name="driverClassName" value="${jdbc.driver}" />服務器

   <!-- 【必須】 數據庫鏈接地址 -->session

   <property name="url" value="${jdbc.url}" />

   <!-- 【必須】 數據庫用戶名 -->

   <property name="username" value="${jdbc.username}" />

   <!-- 【必須】 數據庫密碼 -->

   <property name="password" value="${jdbc.password}" />

   <!-- 可選 啓動時建立的鏈接數 -->

   <property name="initialSize" value="5"/>

   <!-- 可選 同時可從池中分配的最多鏈接數,0無限制 -->

   <property name="maxActive" value="10"/>

   <!-- 可選 池中不會被釋放的最多空閒鏈接數 0無限制 -->

   <property name="maxIdle" value=""/>

   <!-- 可選 同時能從語句池中分配的預處理語句最大值,0無限制 -->

   <property name="maxOpenPreparedStatement" value="100"/>

   <!-- 可選 拋異常前池等待鏈接回收最大時間(當無可用鏈接),-1無限等待 -->

   <property name="maxWait" value="1000"/>

   <!-- 可選 鏈接在池中保持空閒而不被回收的最大時間 -->

   <property name="minEvictableIdleTimeMillis" value="2000"/>

   <!-- 可選 不建立新鏈接狀況下池中保持空閒的最小鏈接數 -->

   <property name="minIdle" value="2"/>

   <!-- 可選 布爾值,是否對預處理語句進行池管理 -->

   <property name="poolPreparedStatements" value="true"/>

</bean>

 

 

C3P0鏈接池:

使用:com.mchange.v2.c3p0.ComboPooledDataSource進行配置

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">

   <property name="driverClass" value="${jdbc.driver}" />

   <property name="jdbcUrl" value="${jdbc.url}" />

   <property name="user" value="${jdbc.username}" />

   <property name="password" value="${jdbc.password}" />

</bean>

 

alibaba DRUID鏈接池:

使用:com.alibaba.druid.pool.DruidDataSource進行配置

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">  

    <!-- 基本屬性 url、user、password --> 

    <property name="url" value="${jdbc_url}" /> 

    <property name="username" value="${jdbc_user}" /> 

    <property name="password" value="${jdbc_password}" /> 

    <!-- 配置初始化大小、最小、最大 --> 

    <property name="initialSize" value="1" /> 

    <property name="minIdle" value="1" />  

    <property name="maxActive" value="20" /> 

    <!-- 配置獲取鏈接等待超時的時間 --> 

    <property name="maxWait" value="60000" /> 

    <!-- 配置間隔多久才進行一次檢測,檢測須要關閉的空閒鏈接,單位是毫秒 --> 

    <property name="timeBetweenEvictionRunsMillis" value="60000" /> 

    <!-- 配置一個鏈接在池中最小生存的時間,單位是毫秒 --> 

    <property name="minEvictableIdleTimeMillis" value="300000" /> 

    <property name="validationQuery" value="SELECT 'x'" /> 

    <property name="testWhileIdle" value="true" /> 

    <property name="testOnBorrow" value="false" /> 

    <property name="testOnReturn" value="false" /> 

    <!-- 打開PSCache,而且指定每一個鏈接上PSCache的大小 --> 

    <property name="poolPreparedStatements" value="true" /> 

    <property name="maxPoolPreparedStatementPerConnectionSize" value="20" /> 

    <!-- 配置監控統計攔截的filters,去掉後監控界面sql沒法統計 --> 

    <property name="filters" value="stat" />  

</bean>

 

 

三、JDBC驅動的數據源

使用:

org.springframework.jdbc.datasource.SingleConnectionDataSource【每一個連接請求會返回同一個鏈接,不推薦】

org.springframework.jdbc.datasource.DriverManagerDataSource進行配置

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">

   <property name="driverClassName" value="${jdbc.driver}" />

   <property name="url" value="${jdbc.url}" />

   <property name="username" value="${jdbc.username}" />

   <property name="password" value="${jdbc.password}" />

</bean>

 

2、操做數據庫

一、spring JDBC模板

模板類選擇:

JdbcTemplate:提供最簡單的數據訪問等功能。

NamedParameterJdbcTemplate:經過該模板,能夠把參數做爲查詢的條件傳入方法中。

SimpleJdbcTemplate(推薦):結合了一些自動裝箱等功能,2.5之後,整合了NamedParameterJdbcTemplate。

配置方式:

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate">

   <constructor-arg ref="dataSource"/>

</bean>

 

二、與ORM框架集成

    主要是配置spring的Session工廠(sessionFactory),可使用到諸如延遲加載、預先抓取、級聯複雜特性。

spring對ORM框架的支持提供提供了一些附加服務:

l  spring聲明式事務集成支持

l  透明的異常處理

l  線程安全、輕量級的模板類

l  DAO支持

l  資源管理

2.一、集成Hibernate方式:[hibernate4爲例]

hibernate的HBM文件配置方式(Xxx.hbm.xml):

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">

   <!-- 數據源 -->

   <property name="dataSource" ref="dataSource" />

   <!-- 映射文件形式-->

   <property name="mappingResources">

      <list>

         <value>User.hbm.xml</value>

      </list>

   </property>

   <!-- Hibernate屬性配置 -->

   <property name="hibernateProperties">

      <props>

         <prop key="dialect">

org.hibernate.dialect.MySQLDialect</prop><!-- 數據庫方言 -->

         <!-- ……其餘 -->

      </props>

   </property>

</bean>

 

代碼中使用註解的方式:

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">

   <!-- 數據源 -->

   <property name="dataSource" ref="dataSource" />  

   <!-- 自動掃描實體對象 tdxy.bean的包結構中存放實體類  -->

   <property name="packagesToScan" value="com.test.entity"/>

   <!-- hibernate的相關屬性配置 -->

   <property name="hibernateProperties">

      <value>

         <!-- 設置數據庫方言 -->

         hibernate.dialect=org.hibernate.dialect.MySQLDialect                

         <!-- 設置自動建立|更新|驗證數據庫表結構 -->

         hibernate.hbm2ddl.auto=update                 

         <!-- 是否在控制檯顯示sql -->

         hibernate.show_sql=true                 

         <!-- 是否格式化sql,優化顯示 -->

         hibernate.format_sql=true                

         <!-- 是否開啓二級緩存 -->

         hibernate.cache.use_second_level_cache=false                

         <!-- 是否開啓查詢緩存 -->

         hibernate.cache.use_query_cache=false                

         <!-- 數據庫批量查詢最大數 -->

         hibernate.jdbc.fetch_size=50

         <!-- 數據庫批量更新、添加、刪除操做最大數  -->

         hibernate.jdbc.batch_size=50                

         <!-- 是否自動提交事務  -->

         hibernate.connection.autocommit=true

         <!-- 指定hibernate在什麼時候釋放JDBC鏈接  -->

         hibernate.connection.release_mode=auto

         <!-- 建立session方式 hibernate4.x 的方式  -->

         hibernate.current_session_context_class=org.springframework.orm.hibernate4.SpringSessionContext

         <!-- javax.persistence.validation.mode默認狀況下是auto的,就是說若是不設置的話它是會自動去你的classpath下面找一個bean-validation**包,因此把它設置爲none便可  -->

         javax.persistence.validation.mode=none            

      </value>

   </property>

</bean>

 

針對少許實體類,還能夠經過annotatedClasses屬性來說應用程序中全部的持久化類以全局定名的方式明確列出:

<property name="annotatedClasses">

   <list>

      <value>com.demo.entity.User</value>

      <value>com.demo.entity.Blog</value>

   </list>

</property>

推薦使用packagesToScan屬性掃描包方式。

 

【構建不依賴於spring的Hibernate代碼】

package com.demo.dao;

 

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Repository;

 

import com.demo.entity.User;

 

@Repository

public class UserDaoImpl implements IUserDao  {

 

   private SessionFactory sessionFactory;

  

   // 構造注入

   @Autowired

   public UserDaoImpl(SessionFactory sessionFactory) {

      this.sessionFactory = sessionFactory;

   }

  

   private Session currentSession(){

      return sessionFactory.getCurrentSession();

   }

  

   @Override

   public void addUser(User param) {

      Session session = currentSession();

      session.save(param);

      System.out.println("Add User");

   }

 

   @Override

   public User get(Integer id) {

      return (User) currentSession().get(User.class, id);

   }

 

   @Override

   public void save(User user) {

      currentSession().update(user);

   }

}

 

還需配置:

<context:component-scan base-package="com.demo.dao"/>

就會像掃描其餘註解同樣掃描帶@Repository註解的類到容器中。

 

2.二、集成MyBatis方式

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"

   p:dataSource-ref="dataSource" p:configLocation="classpath:mybatis-config.xml"

   p:mapperLocations="classpath:com/demo/dao/*.xml" />

<!-- spring與mybatis整合配置,掃描全部dao -->

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"

   p:basePackage="com.demo.dao" p:sqlSessionFactoryBeanName="sqlSessionFactory" />

 

三、與其餘JPA集成方式

3.一、配置實體管理工廠

l  應用程序管理類型的JPA(LocalEntityManagerFactoryBean):它的EntityManager是由EntityManagerFactory建立的;

l  容器管理類型的JPA(LocalContainerEntityManagerFactoryBean):經過PersistenceProvider的createEntityManagerFactory()方法獲得,即它的EntityManagerFactory是經過PersistenceProvider的createContainerEntityManagerFactory()方法獲得。

3.1.一、使用應用程序管理類型的JPA

絕大部分配置文件來源於名爲persistence.xml的配置文件,這個文件位置必須位於類路徑下的WETA-INF目錄下

<?xml version="1.0" encoding="UTF-8"?>

<persistence version="2.0"

      xmlns="http://java.sun.com/xml/ns/persistence"

      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

      xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">

   

   <persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL">

      <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>

      <properties>

         <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />

         <property name="hibernate.max_fetch_depth" value="3"/>

         <property name="hibernate.hbm2ddl.auto" value="update"/>

         <property name="hibernate.jdbc.fetch_size" value="18"/>

         <property name="hibernate.jdbc.batch_size" value="10"/>

         <property name="hibernate.show_sql" value="false"/>

         <property name="hibernate.format_sql" value="false"/>

      </properties>

      <class>com.demo.entity.User</class>

      <class>com.demo.entity.Blog</class>

      <!-- …… ……-->

    </persistence-unit>

 </persistence>

這樣在spring的配置文件中配置的信息就不多了:

<bean id="demo" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">

   <property name="persistenceUnit" >

</bean>

 

【TIPS】上面persistence.xml文件中的配置會出現問題:

若是每次請求EntityManagerFactory時都要定義持久化單元,代碼回迅速膨脹,

藉助spring對JPA的支持,再也不須要直接處理PersistenceProvider了,就是下面的容器管理的JPA!

 

3.1.二、使用容器管理類型的JPA

    將數據源信息配置在spring的應用上下文中,而不是在persistence.xml文件中。

<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

   <property name="dataSource" ref="dataSource"/>

    <!-- 指定使用的是哪個廠商的JPA實現 如Hibernate -->

   <property name="jpaVendorAdapter" ref="hibernateJpaVendorAdapter"/>

</bean>

 

配置JPA實現:

可選的有:EclipseLinkJpaVendorAdapter、HibernateJpaVendorAdapter、OpenJpaVendorAdapter、TopLinkJpaVendorAdapter

<bean id="hibernateJpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">

   <property name="database" value="MYSQL"/>

   <property name="showSql" value="true"/>

   <property name="generateDdl" value="true"/>

   <property name="databasePlatform" value="org.hibernate.dialect.MySQL5Dialect"/>

</bean>

 

【TIPS】database屬性:屬性值表示支持哪一種數據庫,下面Hibernate的JPA是一些支持的數據庫:

數據庫平臺

屬性databased

IBM DB2

DB2

H2

H2

MySQL

MYSQL

Oracle

ORACLE

SQL Server

SQLSERVER

Sybase

SYBASE

PostgresQL

POSTGRESQL

Hypersonic

HSQL

Apache Derby

DERBY

Informix

INFOMIX

 

【注】JNDI獲取實體管理工廠:

若是spring應用部署在應用服務器中,Spring可能已經建立好EntityManagerFactory並將其置於JNDI中等飯查詢使用,這種狀況可以使用JNDI來獲取對EntityManagerFactory的引用:

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

 

3.1.三、編寫基於JPA的DAO

例子:

package com.demo.dao;

 

import javax.persistence.EntityManager;

import javax.persistence.PersistenceContext;

 

import org.springframework.stereotype.Repository;

import org.springframework.transaction.annotation.Transactional;

 

import com.demo.entity.User;

 

@Repository

@Transactional

public class JpaDao implements IUserDao {

 

   // 注入EntityManager

   @PersistenceContext

   private EntityManager em;

  

   // 使用EntityManager

   @Override

   public void addUser(User param) {

      em.persist(param);

 

   }

 

   @Override

   public User get(Integer id) {

      return em.find(User.class, id);

   }

 

   @Override

   public void save(User user) {

      em.merge(user);

   }

}

 

上面使用到了@PersistenceContext註解將EntityManager注入。

這樣用須要在spring的上下文配置文件中配置一個PersistenceAnnotationBeanPostProcessor:

<!-- 使用EntityManager -->

<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>

 

 

以上,是如何使用JDBC、Hibernate或JPA爲spring應用程序構建持久層,至於選擇哪一種方案徹底取決於偏好。

 

3、Spring事務管理

經過毀掉機制將實際事務實現從事務性代碼中抽象出來。

3.一、選擇事務管理器

事務管理器結構

 

事務處理流程:

 

開始事務->綁定資源->使用資源->完成事務->釋放資源

3.1.一、JDBC事務

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

      <property name="dataSource" ref="dataSource"/>

</bean>

DataSourceTransactionManager經過調用java.sql.Connection來管理事務,由java.sql.Connection對象來提交、回滾事務。

3.1.二、Hibernate事務

<bean id="transactionManager"

class="org.springframework.orm.hibernate4.HibernateTransactionManager">

   <property name="sessionFactory" ref="sessionFactory" />

</bean>

HibernateTransactionManager經過將事務管理的職責委託給org.hibernate.Transaction對象,org.hibernate.Transaction對象從Hibernate Session中獲取,而後由Transaction對象來提交、回滾事務。

3.1.三、JPA事務

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">

   <property name="entityManagerFactory" ref="entityManagerFactory"/>

</bean>

JpaTransactionManager只須要裝配一個JPA實體管理工廠(EntityManagerFactory的任意實現),而後與由工廠產生的JPA EntityManager合做構建事務。

         若是你還但願將事務應用於簡單JDBC操做(JDBC操做使用的datasource和EntityManagerFactory使用的dataSource必須相同),那麼JpaTransactionManager必須裝配一個JpaDialect的實現:

<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>

<!--而後將jpaDialect裝配到transactionManager中 -->

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">

   <property name="entityManagerFactory" ref="entityManagerFactory"/>

   <property name="jpaDialect" ref="jpaDialect"/>

</bean>

3.1.四、JTA事務

若是前面的事務管理器不能知足需求或事物須要跨多個事務資源(兩個及以上數據庫),須要使用JtaTrasactionManager了:

<bean id="transactionManager"

   class="org.springframework.transaction.jta.JtaTransactionManager">

   <property name="transactionManagerName" value="java:/TrasactionManager"/>

</bean>

         JtaTransactionManager將事務委託給一個JTA的實現(java.transaction.UserTransaction和javax.transaction.TransactionManager),經過UserTransaction來操做事務。JTA規定了應用程序暈一個或多個數據源之間協調事務的標準API,transactionManagerName屬性指定了要在JNDI上查找JTA事務管理器。

        

3.二、Spring事務實現方式

3.2.一、編碼事務

經過TransactionTemplate的回調機制,例如:(UserSeriveImpl.java)

public void addUser(final User u) {

   TransactionTemplate temp = new TransactionTemplate();

   temp.execute(new TransactionCallback<Void>() {

      @Override

      public Void doInTransaction(TransactionStatus txtStatus) {

           // 要執行的事務代碼

         try {

            userDao.save(u);

         } catch (RuntimeException e) {

            e.printStackTrace();

            txtStatus.setRollbackOnly();

         }

         return null;

      }

   });

}

此時UserService須要以下裝配:

<bean id="userSerive" class="com.demo.service.UserServiceImpl">

   <property name="transactionTemplate">

      <bean class="org.springframework.transaction.support.TransactionTemplate">

         <property name="transactionManager" ref="transactionManager"/>

      </bean>

   </property>

</bean>

優勢:能夠徹底控制事務邊界,精確控制事務。

缺點:侵入性的,事務控制在代碼中實現,耦合度高

3.2.二、聲明式事務

傳播行爲

傳播行爲回答了新的事務是該被啓動仍是被掛起,或者方法是否要在事務環境中運行。

事務的傳播行爲都在org.springframework.transaction.TransactionDefinition接口中以常量的方式定義出來。

隔離級別

隔離級別定義了一個事務可能受其餘併發事務影響的程度。

隔離級別都在org.springframework.transaction.TransactionDefinition接口中以常量的方式定義出來。

只讀

事務啓動的時候由數據庫實施的,只有針對具有啓動一個新事務傳播行爲(PROPAGATION_REQUIREDPROPAGATION_REQUIRES_NEWPROPAGATION_NESTED)的方法來講纔有意義。【tips】若是使用Hibernate,將事務聲明爲只讀會致使flush模式被設置爲FLUSH_NEVER,這會告訴hibernate避免和數據庫進行沒必要要的對象同步,並將全部的更新延遲到事務結束。

事務超時

         長時間事務會致使一些沒必要要的數據庫資源佔用。

         超時時鐘會在事務開始時啓動,只有針對具有啓動一個新事務傳播行爲(PROPAGATION_REQUIREDPROPAGATION_REQUIRES_NEWPROPAGATION_NESTED)的方法來講纔有意義。

回滾規則

         這些規則定義了哪些異常會致使事務回滾哪些不會,默認狀況下,運行時異常會回滾,檢查異常不回滾,可是能夠聲明事務遇到檢查異常回滾,運行時異常不回滾。

3.2.三、Spring在XML中定義事務

須要包括beans、aop、tx命名空間。

<tx:advice id="txAdvice" transaction-manager="transactionManager">

   <tx:attributes>

      <!-- 事務執行方式 REQUIRED:指定當前方法必需在事務環境中運行,

      若是當前有事務環境就加入當前正在執行的事務環境,

      若是當前沒有事務,就新建一個事務。 這是默認值。 -->

      <tx:method name="create*" propagation="REQUIRED" />

      <tx:method name="save*" propagation="REQUIRED" />

      <tx:method name="add*" propagation="REQUIRED" />

      <tx:method name="update*" propagation="REQUIRED" />

      <tx:method name="remove*" propagation="REQUIRED" />

      <tx:method name="del*" propagation="REQUIRED" />

      <tx:method name="import*" propagation="REQUIRED" />

      <!-- 指定當前方法以非事務方式執行操做,若是當前存在事務,就把當前事務掛起,等我以非事務的狀態運行完,再繼續原來的事務。 查詢定義便可

         read-only="true" 表示只讀 -->

      <tx:method name="*" propagation="NOT_SUPPORTED" read-only="true" />

   </tx:attributes>

</tx:advice>

其中<tx:method />有不少屬性用來幫助定義方法的事務策略:

隔離級別

含義

isolation

指定事務隔離級別

propagation

指定事務傳播規則

read-only

指定事務只讀

rollback-for

no-rollback-for

對哪些檢查異常進行回滾不提交

指定對哪些異常繼續執行不回滾

timeout

定義事務超時時間

 

3.2.四、定義註解驅動的事務

在XML配置文件中添加:

<tx:annotation-driven/>

可經過transaction-manager屬性(默認值"transactionManager")來指定事務管理器,如:

<tx:annotation-driven transaction-manager="txManager"/>

<tx:annotation-driven/>告訴Spring檢查上下文中全部bean並檢查使用到@Transactional註解的bean。

相關文章
相關標籤/搜索