天天看點

Spring與JDBC模闆

Spring 所使用的操作資料庫的技術: JDBC 模闆的使用和 Spring 對于事務的管理。

  • JDBC 模闆的使用,是 IoC 的應用,将 JDBC 模闆對象注入給了 Dao 層的實作類。
  • Spring 的事務管理, 是 AOP 的應用,将事務作為切面織入到了 Service 層的業務方法中。

為了避免直接使用 JDBC 而帶來的複雜且冗長的代碼, Spring 提供了一個強有力的模闆類——JdbcTemplate 來簡化 JDBC 操作。并且,資料源 DataSource 對象與模闆 JdbcTemplate 對象均可通過 Bean 的形式定義在配置檔案中,充分發揮了依賴注入的威力。

資料源的配置

使用 JDBC 模闆,首先需要配置好資料源,資料源直接以 Bean 的形式配置在 Spring 配置檔案中。根據資料源的不同,其配置方式不同。常用資料源的配置方式有三種:

  1. Spring 預設的資料源
  2. DBCP 資料源
  3. C3P0 資料源

Spring 預設的資料源

Spring 預設的資料源為 DriverManagerDataSource,其有一個屬性 DriverClassName,用于接收 DB 驅動。DriverManagerDataSource 類繼承自 AbstractDriverBasedDataSource。其有三個屬性用于接收連接配接資料庫的 URL、使用者名與密碼。

<!-- 注冊資料源:Spring内置連接配接池 -->
	<bean id="myDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
		<property name="url" value="jdbc:mysql://localhost:3306/test"/>
		<property name="username" value="root"/>
		<property name="password" value="123456"/>
	</bean>
           

DBCP 資料源

DBCP(DataBase Connection Pool),是 Apache 下的項目,DBCP 資料源是 BasicDataSource,其有 driverClassName、 url、 username、 password 四個 DB 連接配接屬性。

<!-- 注冊資料源:DBCP -->
	<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource">
		<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
		<property name="url" value="jdbc:mysql://localhost:3306/test"/>
		<property name="username" value="root"/>
		<property name="password" value="123456"/>
	</bean>
           

C3P0 資料源

C3P0 資料源是 ComboPooledDataSource ,其有 DriverClass、JdbcUrl、 User、 Password 四個 DB 連接配接屬性。

<!-- 注冊資料源:C3P0 -->
	<bean id="myDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="driverClass" value="${jdbc.driver}"/>
		<property name="jdbcUrl" value="${jdbc.url}"/>
		<property name="user" value="${jdbc.user}"/>
		<property name="password" value="${jdbc.password}"/>
	</bean>
           

從屬性檔案讀取資料庫連接配接資訊

為了便于維護,可以将資料庫連接配接資訊寫入到屬性檔案中,使 Spring 配置檔案從中讀取資料。

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.user=root
jdbc.password=123456
           

Spring 配置檔案從屬性檔案中讀取資料時,需要在<property/>的 value 屬性中使用${ },将在屬性檔案中定義的 key 括起來,以引用指定屬性的值。

Spring與JDBC模闆

該屬性檔案若要被 Spring 配置檔案讀取,其必須在配置檔案中進行注冊。注冊方式有兩種:

  1. <bean/>方式
  2. <context/>方式

<bean/>方式

以 PropertyPlaceholderConfigurer 類的 bean 執行個體的方式進行注冊。該類有一個屬性 location,用于指定屬性檔案的位置。

<!-- 注冊屬性檔案:方式一 -->
	<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="location" value="classpath:jdbc.properties"/>
	</bean>
           

<context:property-placeholder/>方式

<!-- 注冊屬性檔案:方式二 -->
	<context:property-placeholder location="classpath:jdbc.properties"/>
           

注意:

該方式要求在 Spring 配置檔案頭部加入 context 的限制,<context:property-placeholder/>标簽中有一個屬性 location,用于指定屬性檔案的位置。

配置JDBC模闆

JDBC 模闆類 JdbcTemplate 從其父類 JdbcAccessor 繼承了一個屬性 dataSource,用于接收資料源。

<!-- 注冊JdbcTemplate -->
	
	<bean id="myJdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="myDataSource"/>
	</bean>
           

Dao實作類繼承JdbcDaoSupport

JdbcDaoSupport 類中有一個屬性 JdbcTemplate,用于接收 JDBC 模闆。是以 Dao 實作類繼承了 JdbcDaoSupport 類後,也就具有了 JDBC 模闆屬性。在配置檔案中,隻要将模闆對象注入即可。

Spring與JDBC模闆

對DB的增、删、改操作

JdbcTemplate 類中提供了對 DB 進行修改、查詢的方法。 Dao 實作類使用繼承自 JdbcDaoSupport 的 getTemplate()方法,可以擷取到 JDBC 模闆對象。

public interface IStudentDao {
	void insertStudent(Student student);
	void deleteById(int id);
	void updateStudent(Student student);
	
	List<String> selectAllStudentsNames();
	String selectStudentNameById(int id);
	
	List<Student> selectAllStudents();
	Student selectStudnetById(int id);

}
           

對 DB 的增、删、改都是通過 update()方法實作的。該方法常用的重載方法有兩個:

第 1 個參數為要執行的 sql 語句,第 2 個參數為要執行的 sql 語句中所包含的動态參數。其傳回值為所影響記錄的條數。一般不用。

Spring與JDBC模闆

對DB的查詢操作

JDBC 模闆的查詢結果均是以對象的形式傳回。根據傳回對象類型的不同,可以将查詢分為兩類:

  • 簡單對象查詢:查詢結果為 String、 Integer 等簡單對象類型,或該類型做為元素的集合類型,如 List<String>等。
  • 自定義對象查詢:查詢結果為自定義類型,如 User 等,或該類型做為元素的集合類型,如 List<User>等。

簡單對象查詢

常用的簡單對象查詢方法有:查詢結果為單個對象的 queryForObject()與查詢結果為 List 的 queryForList()。

@Override
	public List<String> selectAllStudentsNames() {
		String sql = "select name from student";
		return this.getJdbcTemplate().queryForList(sql, String.class);
	}

	@Override
	public String selectStudentNameById(int id) {
		String sql = "select name from student where id=?";
		return this.getJdbcTemplate().queryForObject(sql, String.class, id);
	}
           

自定義對象查詢

常用的自定義對象查詢方法有:查詢結果為單個對象的 queryForObject()與查詢結果為 List 的 query()。

RowMapper 為記錄映射接口,用于将查詢結果集中每一條記錄包裝為指定對象。該接口中有一個方法需要實作:

參數 rowNum 表示總的結果集中目前行的行号,但參數 rs 并不表示總的結果集,而是表示 rowNum 所代表的目前行的記錄所定義的結果集,僅僅是目前行的結果。一般來說,該方法體中就是實作将查詢結果中目前行的資料包裝為一個指定對象。

public class StudentRowMapper implements RowMapper<Student> {

	// rs:當查詢出總的結果集後,架構會自動周遊這個結果集,每一次周遊的一行資料,都會被存放到
	//     這個方法的rs參數中。也就是說,這裡的rs代表的是一行資料,并非所有查詢結果。換個角度
	//     來說,隻要能執行到這個方法,就說明這裡的rs不會是空的
	@Override
	public Student mapRow(ResultSet rs, int rowNum) throws SQLException {
		Student student = new Student();
		student.setId(rs.getInt("id"));
		student.setName(rs.getString("name"));
		student.setAge(rs.getInt("age"));
		return student;
	}

}
           
@Override
	public List<Student> selectAllStudents() {
		String sql = "select id,name,age from student";
		return this.getJdbcTemplate().query(sql, new StudentRowMapper());
	}

	@Override
	public Student selectStudnetById(int id) {
		String sql = "select id,name,age from student where id=?";
		return this.getJdbcTemplate().queryForObject(sql, new StudentRowMapper(), id);
	}
           

注意:

JdbcTemplate 對象是多例的,即系統會為每一個使用模闆對象的線程(方法)建立一個 JdbcTemplate 執行個體,并且在該線程(方法)結束時,自動釋放 JdbcTemplate 執行個體。是以在每次使用 JdbcTemplate 對象時,都需要通過 getJdbcTemplate()方法擷取。