Spring无论采取哪种数据访问方式,首先都需要一个数据源的引用。Spring提供了在Spring上下文中配置数据源bean的多种方式,包括:
Spring应用程序经常部署在JAVA EE应用服务器中,如WebSphere,JBoss或者Tomcat这样的Web服务器中。这些服务器允许你配置JNDI获取数据源。这样的好处在于数据源完全可以再应用程序之外(如Tomcat的context.xml文件)进行管理。另外,在应用服务器中管理的数据源通常以池的方式组织,从而具备更好的性能,并且还支持管理员对其进行热切换。
下面看一下具体的配置过程:
(1)以Tomcat为例,在conf/context.xml中添加代码:
<Resource
name="jcptDataSourceJNDI"
auth="Container"
type="javax.sql.DataSource"
maxActive="100"
maxIdle="30"
maxWait="10"
username="tysp"
password="12345678"
driverClassName="oracle.jdbc.driver.OracleDriver"
url="jdbc:oracle:thin:@192.168.1.35:1521:orcl"
/>
(2)在应用程序中通过JNDI的方式获取数据源
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>java:comp/env/jcptDataSourceJNDIvalue>
property>
bean>
也可以通过Spring提供的jee标签来配置
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jndi/myDataSource" />
<jee:jndi-lookup id="dataSource" jndi-name="jndi/myDataSource"
resource-ref="true"/>
注意:resource-ref设置为true后,jndi-name会自动添加"java:comp/env/"前缀。
当然,这里也可以使用java配置:
@Bean
public JndiObjectFactoryBean datasource(){
JndiObjectFactoryBean jndiObjectFB = new JndiObjectFactoryBean();
jndiObjectFB.setJndiName("jndi/myDataSource");
jndiObjectFB.setResourceRef(true);
jndiObjectFB.setProxyInterface(javax.sql.DataSource.class);
return jndiObjectFB;
}
如果不是Spring应用程序的话,可以修改web.xml。
<resource-ref>
<description>JNDI DataSourcedescription>
<res-ref-name>jndi/myDataSourceres-ref-name>
<res-type>javax.sql.DataSourceres-type>
<res-auth>Containerres-auth>
resource-ref>
如果不能从JNDI中查找数据源,那么下一个选择就是直接在Spring中配置数据源连接池。Spring有多种开源的方案可供选择:
(1)DBCP
SELECT 1
true
false
当然也可以java配置:
@Bean
public BasicDataSource dataSource(){
BasicDataSource ds = new BasicDataSource();
ds.setDriverClassName(referredDriver);
ds.setUrl(referredDBURL);
ds.setUsername(DBLoginUser);
ds.setPassword(DBLoginUserPassword);
return ds;
}
注意:其中前四个配置是BasicDataSource所必需的。
(2)基于JDBC驱动的数据源
在Spring中,通过JDBC驱动定义数据源是最简单的配置方式。
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${driverClass}">
property>
<property name="url" value="${url}">
property>
<property name="username" value="${username}">property>
<property name="password" value="${password}">property>
bean>
Spring提供了三个这样的数据源(都位于org.springframework.jdbc.datasource中):
注意:SingleConnectionDataSource不适合多线程的应用程序,最好在测试的时候使用。而DriverManagerDataSource和SimpleDriverDataSource尽管支持多线程,但是在每次请求连接使都会创建新连接,而这是以性能为代价的。所以,基于以上这些限制,强烈建议使用数据源连接池。
当然,这里也可以用java配置:
@Bean
public DataSource dataSource(){
DriverManagerDataSource ds= new DriverManagerDataSource();
ds.setDriverClassName(driverClass);
ds.setUrl(url);
ds.setUserName(username);
ds.setPassword(password);
return ds;
}
以前的JDBC代码中,会有大量的代码块都是用于创建连接或者处理异常的样板代码,而且这些样板代码还不能删除,它们在清理资源和处理错误这一块保证了数据访问的健壮性。而Spring的JDBC框架承担了资源管理和异常处理的工作,简化了代码。
Spring提供了三个模板类供选择:
JdbcTemplate:最基本的Spring JDBC模板,这个模板支持简单的JDBC数据库访问功能以及基于索引参数的查询;
NamedParameterJdbcTemplate:使用该模板类执行查询时可以将值以命名参数的形式绑定到SQL中,而不是使用简单的索引参数;
SimpleJdbcTemplate:该模板利用Java5的一些特性如自动装箱,泛型以及可变参数列表来简化JDBC模板的使用。
从Spring3.1开始,SimpleJdbcTemplate就已经被废弃了,Java5的特性被转移到了JdbcTemplate中,并且只有在需要使用命名参数的时候,才需要使用NamedParameterJdbcTemplate。
使用JdbcTemplate来插入数据
为了让JdbcTemplate正常工作,只需要为其设置DataSource就可以了。
xml配置:
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource">property>
bean>
也可以通过java配置
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource){
return new JdbcTemplate(dataSource);
}
如果某一个类需要使用JdbcTemplate,需要在xml文件中配置:
<bean id="userDao" class="com.curd.spring.impl.UserDAOImpl">
<property name="jdbcTemplate" ref="jdbcTemplate">
property>
bean>
JdbcTemplate主要提供了以下方法:
看一下比较简单的例子:
package com.curd.spring.impl;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import com.curd.spring.dao.IUserDAO;
import com.curd.spring.vo.User;
public class UserDAOImpl extends JdbcDaoSupport implements IUserDAO {
public void addUser(User user) {
String sql = "insert into user values(?,?,?)";
this.getJdbcTemplate().update(sql, user.getId(), user.getUsername(),
user.getPassword());
}
public void deleteUser(int id) {
String sql = "delete from user where id=?";
this.getJdbcTemplate().update(sql, id);
}
public void updateUser(User user) {
String sql = "update user set username=?,password=? where id=?";
this.getJdbcTemplate().update(sql, user.getUsername(),
user.getPassword(), user.getId());
}
public String searchUserName(int id) {// 简单查询,按照ID查询,返回字符串
String sql = "select username from user where id=?";
// 返回类型为String(String.class)
return this.getJdbcTemplate().queryForObject(sql, String.class, id);
}
public List<User> findAll() {// 复杂查询返回List集合
String sql = "select * from user";
return this.getJdbcTemplate().query(sql, new UserRowMapper());
}
public User searchUser(int id) {
String sql="select * from user where id=?";
return this.getJdbcTemplate().queryForObject(sql, new UserRowMapper(), id);
}
class UserRowMapper implements RowMapper<User> {
//rs为返回结果集,以每行为单位封装着
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
user.setId(rs.getInt("id"));
user.setUsername(rs.getString("username"));
user.setPassword(rs.getString("password"));
return user;
}
}
}