Spring配置数据源和使用JdbcTemplate模板(四)

Spring配置数据源

Spring无论采取哪种数据访问方式,首先都需要一个数据源的引用。Spring提供了在Spring上下文中配置数据源bean的多种方式,包括:

  • 通过JDBC驱动程序定义的数据源
  • 通过JNDI查找的数据源
  • 连接池的数据源
    对于即将发布到生产环境中的应用程序,建议使用从连接池获取连接的数据源。如果可能的话,更倾向于通过应用服务器的JNDI来获取数据来源。

1.使用JNDI数据源

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/jcptDataSourceJNDI</value>  
  </property>  
</bean>

也可以通过Spring提供的jee标签来配置

<!-- 第一种,不使用resource-ref属性 -->
<jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jndi/myDataSource" />
<!-- 第二种,使用resource-ref属性 -->
<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 DataSource</description>  
     <res-ref-name>jndi/myDataSource</res-ref-name>  
     <res-type>javax.sql.DataSource</res-type>  
     <res-auth>Container</res-auth>  
</resource-ref>

2.使用数据源连接池

如果不能从JNDI中查找数据源,那么下一个选择就是直接在Spring中配置数据源连接池。Spring有多种开源的方案可供选择:

  • Apache的DBCP
  • C3P0
  • BoneCP

(1)DBCP

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">  
        <property name="driverClassName" value="referredDriver" /> 
        <property name="url" value="referredDBURL" />  
        <property name="username" value="DBLoginUser" />  
        <property name="password" value="DBLoginUserPassword" />  
        <!-- 池启动时创建的连接数量 -->
        <property name="initialSize" value="5" />  
        <!-- 池里不会被释放的最多空闲连接数。如果为0,表示无限制 -->
        <property name="maxIdle" value="30" />  
        <property name="minIdle" value="5" />  
        <!--同一时间可从池中分配的最多连接数。如果为0,表示无限制-->
        <property name="maxActive" value="15" />  
        <property name="removeAbandoned" value="true" />  
        <!-- 自动回收超时时间(以秒数为单位) -->  
        <property name="removeAbandonedTimeout" value="300" />  
        <!--超时等待时间以毫秒为单位 -->  
        <property name="maxWait" value="3000" />  
        <property name="defaultAutoCommit" value="false" />  
        <property name="validationQuery">  
            <value>SELECT 1</value>  
        </property>  
        <property name="testOnBorrow">  
            <value>true</value>  
        </property>  
        <property name="testOnReturn">  
            <value>false</value>  
        </property>  
    </bean>

当然也可以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中):

  • DriverManagerDataSource:在每个连接请求时都会返回一个新建的,并没有进行池化管理。
  • SimpleDriverDataSource:直接使用JDBC驱动来解决在特定环境下的类加载问题,这样的环境问题包括OSGI容器。
  • SingleConnectionDataSource:在每个连接请求时都会返回同一个的连接。尽管它不是严格意义上的连接池数据源,但是可以将其视为只有一个连接的池。

注意: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模板

以前的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主要提供了以下方法:

  • execute方法:可用于执行任何SQL语句,一般用于执行DDL语句。
  • update方法以及batchUpdate方法:update方法用于执行新增、修改、删除等语句;batchUpdate方法用于执行批处理相关语句。
  • query方法以及queryForXXX方法:用于执行查询相关语句。
  • call方法:用于执行存储过程、函数相关语句。

看一下比较简单的例子:

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;
        }

    }

}

猜你喜欢

转载自blog.csdn.net/LittleMoon_lyy/article/details/88320678