# 【第八章】 對ORM的支持 之 8.4 集成JPA ——跟我學spring3
## 8.4? 集成JPA
JPA全稱為Java持久性API(Java Persistence API),JPA是Java EE 5標準之一,是一個ORM規范,由廠商來實現該規范,目前有Hibernate、OpenJPA、TopLink、EclipseJPA等實現。
### 8.4.1? 如何集成
Spring目前提供集成Hibernate、OpenJPA、TopLink、EclipseJPA四個JPA標準實現。
Spring通過使用如下Bean進行集成JPA(EntityManagerFactory):
* **LocalEntityManagerFactoryBean:**適用于那些僅使用JPA進行數據訪問的項目,該FactoryBean將根據JPA PersistenceProvider自動檢測配置文件進行工作,一般從“META-INF/persistence.xml”讀取配置信息,這種方式最簡單,但不能設置Spring中定義的DataSource,且不支持Spring管理的全局事務,而且JPA 實現商可能在JVM啟動時依賴于VM agent從而允許它們進行持久化類字節碼轉換(不同的實現廠商要求不同,需要時閱讀其文檔),不建議使用這種方式;
persistenceUnitName:指定持久化單元的名稱;
使用方式:
```
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="persistenceUnit"/>
</bean>
```
* **從JNDI中獲取:**用于從Java EE服務器獲取指定的EntityManagerFactory,這種方式在進行Spring事務管理時一般要使用JTA事務管理;
使用方式:
```
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/jee
http://www.springframework.org/schema/jee/spring-jee-3.0.xsd">
<jee:jndi-lookup id="entityManagerFactory" jndi-name="persistence/persistenceUnit"/>
</beans>
```
此處需要使用“jee”命名標簽,且使用<jee:jndi-lookup>標簽進行JNDI查找,“jndi-name”屬性用于指定JNDI名字。
* **LocalContainerEntityManagerFactoryBean:**適用于所有環境的FactoryBean,能全面控制EntityManagerFactory配置,如指定Spring定義的DataSource等等。
**persistenceUnitManager**:用于獲取JPA持久化單元,默認實現DefaultPersistenceUnitManager用于解決多配置文件情況
**dataSource**:用于指定Spring定義的數據源;
**persistenceXmlLocation**:用于指定JPA配置文件,對于對配置文件情況請選擇設置persistenceUnitManager屬性來解決;
**persistenceUnitName**:用于指定持久化單元名字;
**persistenceProvider**:用于指定持久化實現廠商類;如Hibernate為org.hibernate.ejb.HibernatePersistence類;
**jpaVendorAdapter**:用于設置實現廠商JPA實現的特定屬性,如設置Hibernate的是否自動生成DDL的屬性generateDdl;這些屬性是廠商特定的,因此最好在這里設置;目前Spring提供HibernateJpaVendorAdapter、OpenJpaVendorAdapter、EclipseLinkJpaVendorAdapter、TopLinkJpaVendorAdapter、OpenJpaVendorAdapter四個實現。其中最重要的屬性是“**database**”,用來指定使用的數據庫類型,從而能根據數據庫類型來決定比如如何將數據庫特定異常轉換為Spring的一致性異常,目前支持如下數據庫(**DB2、DERBY、H2、HSQL、INFORMIX、MYSQL、ORACLE、POSTGRESQL、SQL_SERVER、SYBASE**)。
**jpaDialect**:用于指定一些高級特性,如事務管理,獲取具有事務功能的連接對象等,目前Spring提供HibernateJpaDialect、OpenJpaDialect 、EclipseLinkJpaDialect、TopLinkJpaDialect、和DefaultJpaDialect實現,注意DefaultJpaDialect不提供任何功能,因此在使用特定實現廠商JPA實現時需要指定JpaDialect實現,如使用Hibernate就使用HibernateJpaDialect。當指定**jpaVendorAdapter屬性時可以不指定jpaDialect,會自動設置相應的JpaDialect實現;**
**jpaProperties和jpaPropertyMap**:指定JPA屬性;如Hibernate中指定是否顯示SQL的“hibernate.show_sql”屬性,對于jpaProperties設置的屬性自動會放進jpaPropertyMap中;
loadTimeWeaver:用于指定LoadTimeWeaver實現,從而允許JPA 加載時修改相應的類文件。具體使用得參考相應的JPA規范實現廠商文檔,如Hibernate就不需要指定loadTimeWeaver。
接下來學習一下Spring如何集成JPA吧:
**1、準備jar包,從下載的hibernate-distribution-3.6.0.Final包中獲取如下Hibernate需要的jar包從而支持JPA:**
+ lib\jpa\hibernate-jpa-2.0-api-1.0.0.Final.jar //用于支持JPA
**2、對象模型定義,此處使用UserModel2:**
```
package cn.javass.spring.chapter8;
//省略import
@Entity
@Table(name = "test")
public class UserModel2 {
@Id @GeneratedValue(strategy = GenerationType.AUTO)
private int id;
@Column(name = "name")
private String myName;
//省略getter和setter
}
```
注意此處使用的所有注解都是位于javax.persistence包下,如使用@org.hibernate.annotations.Entity 而非@javax.persistence. Entity將導致JPA不能正常工作。
**1、?JPA配置定義(chapter8/persistence.xml),定義對象和數據庫之間的映射:**
```
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.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_1_0.xsd">
<persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL"/>
</persistence>
```
在JPA配置文件中,我們指定要持久化單元名字,和事務類型,其他都將在Spring中配置。
**2、?數據源定義,此處使用第7章的配置文件,即“chapter7/applicationContext-resources.xml”文件。**
**3、?EntityManagerFactory配置定義(chapter8/applicationContext-jpa.xml):**
```
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="persistenceXmlLocation" value="chapter8/persistence.xml"/>
<property name="persistenceUnitName" value="persistenceUnit"/>
<property name="persistenceProvider" ref="persistenceProvider"/>
<property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
<property name="jpaDialect" ref="jpaDialect"/>
<property name="jpaProperties">
<props>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="persistenceProvider" class="org.hibernate.ejb.HibernatePersistence"/>
```
```
<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="generateDdl" value="false" />
<property name="database" value="HSQL"/>
</bean>
<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
```
* **LocalContainerEntityManagerFactoryBean:**指定使用本地容器管理EntityManagerFactory,從而進行細粒度控制;
* **dataSource**屬性指定使用Spring定義的數據源;
* **persistenceXmlLocation**指定JPA配置文件為chapter8/persistence.xml,且該配置文件非常簡單,具體配置完全在Spring中進行;
* **persistenceUnitName**指定持久化單元名字,即JPA配置文件中指定的;
* **persistenceProvider**:指定JPA持久化提供商,此處使用Hibernate實現HibernatePersistence類;
* **jpaVendorAdapter**:指定實現廠商專用特性,即generateDdl= false表示不自動生成DDL,database= HSQL表示使用hsqldb數據庫;
* **jpaDialect**:如果指定jpaVendorAdapter此屬性可選,此處為HibernateJpaDialect;
* **jpaProperties**:此處指定“hibernate.show_sql =true”表示在日志系統debug級別下將打印所有生成的SQL。
**4、?獲取EntityManagerFactory:**
```
package cn.javass.spring.chapter8;
//省略import
public class JPATest {
private static EntityManagerFactory entityManagerFactory;
@BeforeClass
public static void setUpClass() {
String[] configLocations = new String[] {
"classpath:chapter7/applicationContext-resources.xml",
"classpath:chapter8/applicationContext-jpa.xml"};
ApplicationContext ctx = new ClassPathXmlApplicationContext(configLocations);
entityManagerFactory = ctx.getBean(EntityManagerFactory.class);
}
}
```
此處我們使用了chapter7/applicationContext-resources.xml定義的“dataSource”數據源,通過ctx.getBean(EntityManagerFactory.class)獲取EntityManagerFactory。
5、? 通過EntityManagerFactory獲取EntityManager進行創建和刪除表:
```
@Before
public void setUp() throws SQLException {
//id自增主鍵從0開始
String createTableSql = "create memory table test" + "(id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, " + "name varchar(100))";
executeSql(createTableSql);
}
@After
public void tearDown() throws SQLException {
String dropTableSql = "drop table test";
executeSql(dropTableSql);
}
private void executeSql(String sql) throws SQLException {
EntityManager em = entityManagerFactory.createEntityManager();
beginTransaction(em);
em.createNativeQuery(sql).executeUpdate();
commitTransaction(em);
closeEntityManager(em);
}
private void closeEntityManager(EntityManager em) {
em.close();
}
private void rollbackTransacrion(EntityManager em) throws SQLException {
if(em != null) {
em.getTransaction().rollback();
}
}
private void commitTransaction(EntityManager em) throws SQLException {
em.getTransaction().commit();
}
private void beginTransaction(EntityManager em) throws SQLException {
em.getTransaction().begin();
}
```
使用EntityManagerFactory創建EntityManager,然后通過EntityManager對象的createNativeQuery創建本地SQL執行創建和刪除表。
**6、?使用EntityManagerFactory獲取EntityManager對象進行持久化數據:**
```
@Test
public void testFirst() throws SQLException {
UserModel2 model = new UserModel2();
model.setMyName("test");
EntityManager em = null;
try {
em = entityManagerFactory.createEntityManager();
beginTransaction(em);
em.persist(model);
commitTransaction(em);
} catch (SQLException e) {
rollbackTransacrion(em);
throw e;
} finally {
closeEntityManager(em);
}
}
```
使用**EntityManagerFactory**獲取**EntityManager**進行操作,看到這還能忍受冗長的代碼和事務管理嗎?Spring同樣提供JpaTemplate模板類來簡化這些操作。
大家有沒有注意到此處的模型對象能自動映射到數據庫,這是因為Hibernate JPA實現默認自動掃描類路徑中的@Entity注解類及*.hbm.xml映射文件,可以通過更改Hibernate JPA屬性“hibernate.ejb.resource_scanner”,并指定org.hibernate.ejb.packaging.Scanner接口實現來定制新的掃描策略。
### 8.4.2? 使用JpaTemplate
JpaTemplate模板類用于簡化事務管理及常見操作,類似于JdbcTemplate模板類,對于復雜操作通過提供JpaCallback回調接口來允許更復雜的操作。
接下來示例一下JpaTemplate的使用:
**1、修改Spring配置文件(chapter8/applicationContext-jpa.xml),添加JPA事務管理器:**
```
<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
```
* txManager:指定事務管理器,JPA使用JpaTransactionManager事務管理器實現,通過entityManagerFactory指定EntityManagerFactory;用于支持Java SE環境的**JPA擴展的持久化上下文(EXTENDED Persistence Context)**。
**2、修改JPATest類,添加類變量ctx,用于后邊使用其獲取事務管理器使用:**
```
package cn.javass.spring.chapter8;
public class JPATest {
private static EntityManagerFactory entityManagerFactory;
private static ApplicationContext ctx;
@BeforeClass
public static void beforeClass() {
String[] configLocations = new String[] {
"classpath:chapter7/applicationContext-resources.xml",
"classpath:chapter8/applicationContext-jpa.xml"};
ctx = new ClassPathXmlApplicationContext(configLocations);
entityManagerFactory = ctx.getBean(EntityManagerFactory.class);
}
}
```
**3)JpaTemplate模板類使用:**
```
@Test
public void testJpaTemplate() {
final JpaTemplate jpaTemplate = new JpaTemplate(entityManagerFactory);
final UserModel2 model = new UserModel2();
model.setMyName("test1");
PlatformTransactionManager txManager = ctx.getBean(PlatformTransactionManager.class);
new TransactionTemplate(txManager).execute(
new TransactionCallback<Void>() {
@Override
public Void doInTransaction(TransactionStatus status) {
jpaTemplate.persist(model);
return null;
}
});
String COUNT_ALL = "select count(*) from UserModel";
Number count = (Number) jpaTemplate.find(COUNT_ALL).get(0);
Assert.assertEquals(1, count.intValue());
}
```
* **jpaTemplate**:可通過new JpaTemplate(entityManagerFactory)方式創建;
* **txManager:**通過ctx.getBean(PlatformTransactionManager.class)獲取事務管理器;
* **TransactionTemplate:**通過new TransactionTemplate(txManager)創建事務模板對象,并通過execute方法執行TransactionCallback回調中的doInTransaction方法中定義需要執行的操作,從而將由模板類通過txManager事務管理器來進行事務管理,此處是調用jpaTemplate對象的persist方法進行持久化;
* **jpaTemplate.persist()**:根據JPA規范,在JPA擴展的持久化上下文,該操作必須運行在事務環境,還有persist()、 merge()、remove()操作也必須運行在事務環境;
* **jpaTemplate.find():**根據JPA規范,該操作無需運行在事務環境,還有find()、getReference()、 refresh()、detach()和查詢操作都無需運行在事務環境。
此實例與Hibernate和Ibatis有所區別,通過JpaTemplate模板類進行如持久化等操作時必須有運行在事務環境中,否則可能拋出如下異常或警告:
* **“javax.persistence.TransactionRequiredException:Executing an update/delete query”**:表示沒有事務支持,不能執行更新或刪除操作;
* **警告“delaying identity-insert due to no transaction in progress”:**需要在日志系統啟動debug模式才能看到,表示在無事務環境中無法進行持久化,而選擇了延遲標識插入。
以上異常和警告是沒有事務造成的,也是最讓人困惑的問題,需要大家注意。
### 8.4.3? 集成JPA及最佳實踐
類似于JdbcDaoSupport類,Spring對JPA也提供了JpaDaoSupport類來支持一致的數據庫訪問。JpaDaoSupport也是DaoSupport實現:
接下來示例一下Spring集成JPA的最佳實踐:
**1、?定義Dao接口,此處使用cn.javass.spring.chapter7.dao. IUserDao:**
**2、?定義Dao接口實現,此處是JPA實現:**
```
package cn.javass.spring.chapter8.dao.jpa;
//省略import
@Transactional(propagation = Propagation.REQUIRED)
public class UserJpaDaoImpl extends JpaDaoSupport implements IUserDao {
private static final String COUNT_ALL_JPAQL = "select count(*) from UserModel";
@Override
public void save(UserModel model) {
getJpaTemplate().persist(model);
}
@Override
public int countAll() {
Number count =
(Number) getJpaTemplate().find(COUNT_ALL_JPAQL).get(0);
return count.intValue();
}
}
```
此處注意首先JPA實現放在dao.jpa包里,其次實現類命名如UserJpaDaoImpl,即×××JpaDaoImpl,當然如果自己有更好的命名規范可以遵循自己的,此處只是提個建議。
另外在類上添加了**@Transactional**注解表示該類的所有方法將在調用時需要事務支持,propagation傳播屬性為Propagation.REQUIRED表示事務是必需的,如果執行該類的方法沒有開啟事務,將開啟一個新的事務。
**3、進行資源配置,使用resources/chapter7/applicationContext-resources.xml:**
**4、dao定義配置,在chapter8/applicationContext-jpa.xml中添加如下配置:**
**4.1、**首先添加tx命名空間用于支持事務:
```
<?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:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
```
4.2、為**@Transactional**注解事務開啟事務支持:
```
<tx:annotation-driven transaction-manager="txManager"/>
```
只為類添加**@Transactional**?注解是不能支持事務的,需要通過<tx:annotation-driven>標簽來開啟事務支持,其中txManager屬性指定事務管理器。
4.3、配置DAO Bean:
```
<bean id="abstractDao" abstract="true">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<bean id="userDao"
class="cn.javass.spring.chapter8.dao.jpa.UserJpaDaoImpl"
parent="abstractDao"/>
```
首先定義抽象的abstractDao,其有一個entityManagerFactory屬性,從而可以讓繼承的子類自動繼承entityManagerFactory屬性注入;然后定義userDao,且繼承abstractDao,從而繼承entityManagerFactory注入;我們在此給配置文件命名為applicationContext-jpa.xml表示JPA實現。
**5、最后測試一下吧(cn.javass.spring.chapter8\. JPATest):**
```
@Test
public void testBestPractice() {
String[] configLocations = new String[] {
"classpath:chapter7/applicationContext-resources.xml",
"classpath:chapter8/applicationContext-jpa.xml"};
ApplicationContext ctx = new ClassPathXmlApplicationContext(configLocations);
IUserDao userDao = ctx.getBean(IUserDao.class);
UserModel model = new UserModel();
model.setMyName("test");
userDao.save(model);
Assert.assertEquals(1, userDao.countAll());
}
```
和Spring JDBC框架的最佳實踐完全一樣,除了使用applicationContext-jpa.xml代替了applicationContext-jdbc.xml,其他完全一樣。也就是說,DAO層的實現替換可以透明化。
還有與集成其他ORM框架不同的是JPA在進行持久化或更新數據庫操作時需要事務支持。
### 8.4.4? Spring+JPA的CRUD
Spring+JPA CRUD(增刪改查)也相當簡單,讓我們直接看具體示例吧:
```
@Test
public void testCRUD() {
PlatformTransactionManager txManager = ctx.getBean(PlatformTransactionManager.class);
final JpaTemplate jpaTemplate = new JpaTemplate(entityManagerFactory);
TransactionTemplate tansactionTemplate = new TransactionTemplate(txManager);
tansactionTemplate.execute(new TransactionCallback<Void>() {
@Override
public Void doInTransaction(TransactionStatus status) {
UserModel model = new UserModel();
model.setMyName("test");
//新增
jpaTemplate.persist(model);
//修改
model.setMyName("test2");
jpaTemplate.flush();//可選
//查詢
String sql = "from UserModel where myName=?";
List result = jpaTemplate.find(sql, "test2");
Assert.assertEquals(1, result.size());
//刪除
jpaTemplate.remove(model);
return null;
}
});
}
```
* 對于增刪改必須運行在事務環境,因此我們使用TransactionTemplate事務模板類來支持事務。
* 持久化:使用JpaTemplate 類的persist方法持久化模型對象;
* 更新:對于持久化狀態的模型對象直接修改屬性,調用flush方法即可更新到數據庫,在一些場合時flush方法調用可選,如執行一個查詢操作等,具體請參考相關文檔;
* 查詢:可以使用find方法執行JPA QL查詢;
* 刪除:使用remove方法刪除一個持久化狀態的模型對象。
Spring集成JPA進行增刪改查也相當簡單,但本文介紹的稍微復雜一點,因為牽扯到編程式事務,如果采用聲明式事務將和集成Hibernate方式一樣簡潔。
原創內容,轉載請注明出處【[http://sishuok.com/forum/blogPost/list/0/2500.html](http://sishuok.com/forum/blogPost/list/0/2500.html#7218)】
- 跟我學 Spring3
- 【第二章】 IoC 之 2.1 IoC基礎 ——跟我學Spring3
- 【第二章】 IoC 之 2.2 IoC 容器基本原理 ——跟我學Spring3
- 【第二章】 IoC 之 2.3 IoC的配置使用——跟我學Spring3
- 【第三章】 DI 之 3.1 DI的配置使用 ——跟我學spring3
- 【第三章】 DI 之 3.2 循環依賴 ——跟我學spring3
- 【第三章】 DI 之 3.3 更多DI的知識 ——跟我學spring3
- 【第三章】 DI 之 3.4 Bean的作用域 ——跟我學spring3
- 【第四章】 資源 之 4.1 基礎知識 ——跟我學spring3
- 【第四章】 資源 之 4.2 內置Resource實現 ——跟我學spring3
- 【第四章】 資源 之 4.3 訪問Resource ——跟我學spring3
- 【第四章】 資源 之 4.4 Resource通配符路徑 ——跟我學spring3
- 【第五章】Spring表達式語言 之 5.1 概述 5.2 SpEL基礎 ——跟我學spring3
- 【第五章】Spring表達式語言 之 5.3 SpEL語法 ——跟我學spring3
- 【第五章】Spring表達式語言 之 5.4在Bean定義中使用EL—跟我學spring3
- 【第六章】 AOP 之 6.1 AOP基礎 ——跟我學spring3
- 【第六章】 AOP 之 6.2 AOP的HelloWorld ——跟我學spring3
- 【第六章】 AOP 之 6.3 基于Schema的AOP ——跟我學spring3
- 【第六章】 AOP 之 6.4 基于@AspectJ的AOP ——跟我學spring3
- 【第六章】 AOP 之 6.5 AspectJ切入點語法詳解 ——跟我學spring3
- 【第六章】 AOP 之 6.6 通知參數 ——跟我學spring3
- 【第六章】 AOP 之 6.7 通知順序 ——跟我學spring3
- 【第六章】 AOP 之 6.8 切面實例化模型 ——跟我學spring3
- 【第六章】 AOP 之 6.9 代理機制 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.1 概述 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.2 JDBC模板類 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.3 關系數據庫操作對象化 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.4 Spring提供的其它幫助 ——跟我學spring3【私塾在線原創】
- 【第七章】 對JDBC的支持 之 7.5 集成Spring JDBC及最佳實踐 ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.1 概述 ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.2 集成Hibernate3 ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.3 集成iBATIS ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.4 集成JPA ——跟我學spring3
- 【第九章】 Spring的事務 之 9.1 數據庫事務概述 ——跟我學spring3
- 【第九章】 Spring的事務 之 9.2 事務管理器 ——跟我學spring3
- 【第九章】 Spring的事務 之 9.3 編程式事務 ——跟我學spring3
- 【第九章】 Spring的事務 之 9.4 聲明式事務 ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.1 概述 ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.2 集成Struts1.x ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.3 集成Struts2.x ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.4 集成JSF ——跟我學spring3
- 【第十一章】 SSH集成開發積分商城 之 11.1 概述 ——跟我學spring3
- 【第十一章】 SSH集成開發積分商城 之 11.2 實現通用層 ——跟我學spring3
- 【第十一章】 SSH集成開發積分商城 之 11.3 實現積分商城層 ——跟我學spring3
- 【第十二章】零配置 之 12.1 概述 ——跟我學spring3
- 【第十二章】零配置 之 12.2 注解實現Bean依賴注入 ——跟我學spring3
- 【第十二章】零配置 之 12.3 注解實現Bean定義 ——跟我學spring3
- 【第十二章】零配置 之 12.4 基于Java類定義Bean配置元數據 ——跟我學spring3
- 【第十二章】零配置 之 12.5 綜合示例-積分商城 ——跟我學spring3
- 【第十三章】 測試 之 13.1 概述 13.2 單元測試 ——跟我學spring3
- 【第十三章】 測試 之 13.3 集成測試 ——跟我學spring3
- 跟我學 Spring MVC
- SpringMVC + spring3.1.1 + hibernate4.1.0 集成及常見問題總結
- Spring Web MVC中的頁面緩存支持 ——跟我學SpringMVC系列
- Spring3 Web MVC下的數據類型轉換(第一篇)——《跟我學Spring3 Web MVC》搶先看
- Spring3 Web MVC下的數據格式化(第二篇)——《跟我學Spring3 Web MVC》搶先看
- 第一章 Web MVC簡介 —— 跟開濤學SpringMVC
- 第二章 Spring MVC入門 —— 跟開濤學SpringMVC
- 第三章 DispatcherServlet詳解 ——跟開濤學SpringMVC
- 第四章 Controller接口控制器詳解(1)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(2)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(3)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解 (4)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(5)——跟著開濤學SpringMVC
- 跟著開濤學SpringMVC 第一章源代碼下載
- 第二章 Spring MVC入門 源代碼下載
- 第四章 Controller接口控制器詳解 源代碼下載
- 第四章 Controller接口控制器詳解(6)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(7 完)——跟著開濤學SpringMVC
- 第五章 處理器攔截器詳解——跟著開濤學SpringMVC
- 源代碼下載 第五章 處理器攔截器詳解——跟著開濤學SpringMVC
- 注解式控制器運行流程及處理器定義 第六章 注解式控制器詳解——跟著開濤學SpringMVC
- 源代碼下載 第六章 注解式控制器詳解
- SpringMVC3強大的請求映射規則詳解 第六章 注解式控制器詳解——跟著開濤學SpringMVC
- Spring MVC 3.1新特性 生產者、消費者請求限定 —— 第六章 注解式控制器詳解——跟著開濤學SpringMVC
- SpringMVC強大的數據綁定(1)——第六章 注解式控制器詳解——跟著開濤學SpringMVC
- SpringMVC強大的數據綁定(2)——第六章 注解式控制器詳解——跟著開濤學SpringMVC
- SpringMVC數據類型轉換——第七章 注解式控制器的數據驗證、類型轉換及格式化——跟著開濤學SpringMVC
- SpringMVC數據格式化——第七章 注解式控制器的數據驗證、類型轉換及格式化——跟著開濤學SpringMVC
- SpringMVC數據驗證——第七章 注解式控制器的數據驗證、類型轉換及格式化——跟著開濤學SpringMVC