DAO 支援

Spring 的 Data Access Object (DAO) 支援旨在提供一種一致的方式,使處理資料訪問技術(如 JDBC、Hibernate 或 JPA)變得容易。這使你可以相當輕鬆地在上述持久化技術之間切換,並且無需擔心捕獲特定於每種技術的異常即可編寫程式碼。

一致的異常層次結構

Spring 提供了一種便捷的轉換,將技術特定的異常(如 SQLException)轉換為它自己的異常類層次結構,該層次結構的根異常是 DataAccessException。這些異常會包裝原始異常,因此你絕不會有丟失有關發生錯誤的資訊的風險。

除了 JDBC 異常外,Spring 還可以包裝 JPA 和 Hibernate 特定的異常,將它們轉換為一組集中的執行時異常。這使得你可以在適當的層中處理大多數不可恢復的持久化異常,而無需在你的 DAO 中編寫煩人的樣板 catch-and-throw 程式碼塊和異常宣告。(當然,你仍然可以在需要的地方捕獲和處理異常。)如上所述,JDBC 異常(包括資料庫特定的方言)也會被轉換到相同的層次結構中,這意味著你可以在一致的程式設計模型中執行一些 JDBC 操作。

前面的討論對於 Spring 支援各種 ORM 框架中的各種模板類同樣適用。如果你使用基於攔截器的類,應用程式本身必須處理 HibernateExceptionsPersistenceExceptions,最好分別委託給 SessionFactoryUtilsconvertHibernateAccessException(..)convertJpaAccessException(..) 方法。這些方法將異常轉換為與 org.springframework.dao 異常層次結構中的異常相容的異常。由於 PersistenceExceptions 是 unchecked 異常,它們也可以被丟擲(儘管犧牲了異常層面的通用 DAO 抽象)。

下圖展示了 Spring 提供的異常層次結構。(請注意,圖片中詳細的類層次結構僅顯示了整個 DataAccessException 層次結構的一部分。)

DataAccessException

用於配置 DAO 或 Repository 類的註解

確保你的 Data Access Objects (DAO) 或 repository 提供異常轉換的最佳方法是使用 `@Repository` 註解。這個註解還允許元件掃描支援找到並配置你的 DAO 和 repository,而無需為其提供 XML 配置條目。以下示例展示瞭如何使用 `@Repository` 註解

  • Java

  • Kotlin

@Repository (1)
public class SomeMovieFinder implements MovieFinder {
	// ...
}
1 `@Repository` 註解。
@Repository (1)
class SomeMovieFinder : MovieFinder {
	// ...
}
1 `@Repository` 註解。

任何 DAO 或 repository 實現都需要訪問持久化資源,這取決於所使用的持久化技術。例如,基於 JDBC 的 repository 需要訪問 JDBC DataSource,而基於 JPA 的 repository 需要訪問 EntityManager。最簡單的方法是使用 `@Autowired`、`@Inject`、`@Resource` 或 `@PersistenceContext` 註解中的一個來注入這個資源依賴。以下示例適用於 JPA repository

  • Java

  • Kotlin

@Repository
public class JpaMovieFinder implements MovieFinder {

	@PersistenceContext
	private EntityManager entityManager;

	// ...
}
@Repository
class JpaMovieFinder : MovieFinder {

	@PersistenceContext
	private lateinit var entityManager: EntityManager

	// ...
}

如果你使用經典的 Hibernate API,可以注入 SessionFactory,如下例所示

  • Java

  • Kotlin

@Repository
public class HibernateMovieFinder implements MovieFinder {

	private SessionFactory sessionFactory;

	@Autowired
	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	// ...
}
@Repository
class HibernateMovieFinder(private val sessionFactory: SessionFactory) : MovieFinder {
	// ...
}

這裡展示的最後一個示例是針對典型的 JDBC 支援。你可以將 DataSource 注入到初始化方法或建構函式中,在那裡可以使用此 DataSource 建立 JdbcTemplate 和其他資料訪問支援類(如 SimpleJdbcCall 等)。以下示例自動裝配一個 DataSource

  • Java

  • Kotlin

@Repository
public class JdbcMovieFinder implements MovieFinder {

	private JdbcTemplate jdbcTemplate;

	@Autowired
	public void init(DataSource dataSource) {
		this.jdbcTemplate = new JdbcTemplate(dataSource);
	}

	// ...
}
@Repository
class JdbcMovieFinder(dataSource: DataSource) : MovieFinder {

	private val jdbcTemplate = JdbcTemplate(dataSource)

	// ...
}
有關如何配置應用程式上下文以利用這些註解的詳細資訊,請參閱每種持久化技術的具體介紹。