ITEEDU

DataSource  注入

对于不同的资料连接来源需求,Spring 提供了 javax.sql.DataSource 注入,更换资料来源只要 在 Bean 定义档中修改配置,而不用修改任何一行程式。

因应不同的系统,应用程式可能使用不同的资料来源,例如纯綷的使用 JDBC、透过连接池、或 是透过 JNDI 等等,资料来源的更动是底层的行为,这些行为不 应影响到上层的业务逻辑,为此, 您可以在需要取得连接来源的 Bean 物件上保留一个 Datasource 注入的操作介面, Spring 提供 org.springframework.jdbc.datasource.DriverManagerDataSource 来取得它的 实例, DriverManagerDataSource 实作了 javax.sql.DataSource,您可以在 Bean 定义档中这么撰写:

...
<beans>
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDat
		aSource ">
		<property name="driverClassName">
			<value>com.mysql.jdbc.Driver</value>
		</property>
		<property name="url">
			<value>jdbc:mysql://localhost:3306/demo</value>
		</property>
		<property name="username">
			<value>caterpillar</value>
		</property>
		<property name="password">
			<value>123456</value>
		</property>
	</bean>
	...
</beans>

其中"driverClassName"、"url"、"username"、"password"四个属性分别用来设定 JDBC 驱动程 式类别、资料库 URL 协定、使用者名称、密码。 在这边实际使用一个程式来作为 DataSource 注入的示范,并也示范一下之前有关于 DAO 介绍的 实作,假设您定义了一个 DAO 的操作介面如下:

•      IUserDAO.java
package onlyfun.caterpillar;
public interface IUserDAO {
	public void insert(User user);
	public User find(Integer id);
}

这边关于 DAO 的介面定义只有 insert()与 find()两个方法。在这个介面中所使用到的 User 类别 则如下定义:

•      User.java
package onlyfun.caterpillar;
public class User { private Integer id; private String name; private Integer age;
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {

		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
}

接着您可以定义一个 UserDAO 类别,它实作了 IUserDAO 介面,是实际进行资料库存取服务的物 件,如下所示:

•      UserDAO.java
package onlyfun.caterpillar;
import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement;
import javax.sql.DataSource;
public class UserDAO implements IUserDAO {
	private DataSource dataSource;
	public void setDataSource(DataSource dataSource) {
		this.dataSource = dataSource;
	}
	public void insert(User user) { String name = user.getName();
		int age = user.getAge().intValue();
		Connection conn = null; Statement stmt = null;
		try {
			conn = dataSource.getConnection();
			stmt = conn.createStatement();
			stmt.execute("INSERT INTO user (name,age) "	+ "VALUES('" + name + "'," + age + ")");
		} catch (SQLException e) {
			e.printStackTrace();
		}
		finally {
			if(stmt != null) {
				try {
					stmt.close();
				}
				catch(SQLException e) {
					e.printStackTrace();
				}
			}
			if(conn != null) {
				try {
					conn.close();
				}
				catch(SQLException e) {
					e.printStackTrace();
				}
			}
		}
	}
	public User find(Integer id) { Connection conn = null; Statement stmt = null;
		try {
			conn = dataSource.getConnection();
			stmt = conn.createStatement();
			ResultSet result = stmt.executeQuery("SELECT * FROM user WHERE id=" + id.intValue());
			if(result.next()) {
				Integer i = new Integer(result.getInt(1));
				String name = result.getString(2);
				Integer age = new Integer(result.getInt(3));
				// 封装为 User 物件
				User user = new User();
				user.setId(i);
				user.setName(name);
				user.setAge(age);
				return user;
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		finally {
			if(stmt != null) {
				try {
					stmt.close();
				}
				catch(SQLException e) {
					e.printStackTrace();
				}
			}
			if(conn != null) {
				try {
					conn.close();
				}
				catch(SQLException e) {
					e.printStackTrace();
				}
			}
		}
		return null;
	}
}

UserDAO 类别上宣告了一个 setDataSource()方法,可以让您注入 DataSource 的实例,您可以在 Bean 定义档中进行依赖注入的定义,如下所示:

•      beans-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING/DTD BEAN/EN""http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
	<bean id="dataSource"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName">
			<value>com.mysql.jdbc.Driver</value>
		</property>
		<property name="url">
			<value>jdbc:mysql://localhost:3306/demo</value>
		</property>
		<property name="username">
			<value>caterpillar</value>
		</property>
		<property name="password">
			<value>123456</value>
		</property>
	</bean>
	<bean id="userDAO" class="onlyfun.caterpillar.UserDAO">
		<property name="dataSource">
			<ref bean="dataSource"/>
		</property>
	</bean>
</beans>

可以撰写一个简单的测试程式来操作 UserDAO 的实例,看看是否能进行资料的储存与查询:

•      SpringAOPDemo.java
package onlyfun.caterpillar;
import org.springframework.context.ApplicationContext;
import org.springframework.context. support.FileSystemXmlApplicationContext;
public class SpringDAODemo {
	public static void main(String[] args) { ApplicationContext context =
		new FileSystemXmlApplicationContext( "beans-config.xml");
		User user = new User();

		user.setName("caterpillar");
		user.setAge(new Integer(30));
		IUserDAO userDAO =
		(IUserDAO) context.getBean("userDAO");
		userDAO.insert(user);
		user = userDAO.find(new Integer(1));
		System.out.println("name: " + user.getName());
	}
}

在进行程式的测试之前,当然的您要先开启资料库服务,并将 beans-config.xml 中相关的驱动 程式类别、资料库 URL、使用者名称与密码等修改为您的设定,在这边我所使用的是 MySQL 资料 库,而我所建立的 user 表格是使用以下的 SQL 来建立的:

CREATE TABLE user (
	id INT(11) NOT NULL auto_increment PRIMARY KEY, 
	name VARCHAR(100) NOT NULL default '',
	age INT
);

程式的执行结果会先在资料库的 user 表格中存入一笔资料,接着根据 id 值查询出先前所存入的 资料,最后结果会显示"name: caterpillar"的文字。

您 需 要 spring-core.jar 、 spring-beans.jar 、 spring-context.jar 、 spring-dao.jar 与 spring-jdbc.jar 这几个档案,如果您使用的是 spring.jar,当中已经包括了相关 API,另外也 需要相依的 commons- logging.jar,当然,为了使用 JDBC,您必须要有 JDBC 驱动程式的 jar 档。