Spring框架:Spring与持久化

Spring的持久化用于简化数据的操作。


数据源

数据源有多种类型:JNDI、连接池、JDBC。


JNDI的配置方法。例子中使用Tomcat作为Web容器。首先要在context.xml中加上下面这段代码。

<Resource name="jdbc/TestDB" auth="Container" type="javax.sql.DataSource"
               maxActive="100" maxIdle="30" maxWait="10000"
               username="javauser" password="javadude" driverClassName="com.mysql.jdbc.Driver"
               url="jdbc:mysql://localhost:3306/javatest"/>

重启Tomcat之后就可以在应用中通过下面的配置直接访问数据源了。

<jee:jndi-lookup id="dataSource" jndi-name="/jdbc/TestDB" resource-ref="true"/>


连接池配置。另外一种方法是使用数据库连接池作为数据源。一般比较主流的连接池为Apache DBCP。它需要像下面这样配置。

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
  <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
  <property name="url" value="jdbc:mysql://localhost:3306/javatest"/>
  <property name="username" value="root"/>
  <property name="password" value="123456"/>
  <property name="initialSize" value="5"/>
  <property name="maxActive" value="10"/>
</bean>


JDBC配置。

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
  <property name="url" value="jdbc:mysql://localhost:3306/javatest"/>
  <property name="username" value="test"/>
  <property name="password" value="test"/>
</bean>


JDBC模板

写过JDBC程序的人都知道,异常处理部分占据了很多代码。为了消灭这些样板代码,Spring提供了JDBC模板。


下面将通过例子介绍如何使用JdbcTemplate访问数据。首先是bean的配置,创建一个全局的jdbcTemplate。

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
  <constructor-arg ref="dataSource"/>
</bean>


下面的例子演示了插入一行新数据的过程。

// 匿名参数
public void addUser(User user) {
    jdbcTemplate.update("INSERT INTO user (username,password) VALUES (?,?)",
        user.getUsername(),
        user.getPassword());
}

// 命名参数
public void addUser(User user) {
    Map<String, Object> params = new HashMap<String, Object>();
    params.put("username", user.getUsername());
    params.put("password", user.getPassword());
    jdbcTemplate.update("INSERT INTO user (username,password) VALUES (:username, :password)", params);
}


下面的例子演示了从数据库中读取数据的过程。其中RowMapper的作用是将一行数据转换为一个对象。

public List<User> getUserList() {
    return jdbcTemplate.query(
        "SELECT id,username,password FROM user",
        new RowMapper<User>() {
            public User mapRow(ResultSet rs, int rowNum) throws SQLException {
                User user = new User();
                user.setId(rs.getInt(1));
                user.setUsername(rs.getNString(2));
                user.setPassword(rs.getNString(3));
                return user;
            }
        }
    );
}


事务

Spring中的事务是通过专门的类来管理的,名为TransactionManager。需要如下的bean配置。

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" ref="dataSource"/>
</bean>

配置完成之后就可以使用transactionManager执行事务了。下面是执行事务的例子。

public void test() {
    transactionTemplate.execute(new TransactionCallback<Void>() {
        public Void doInTransaction(TransactionStatus status) {
            jdbcTemplate.update("INSERT INTO ...",x,y,z);
        }
    }
}

从代码中可以看到transactionTemplate和jdbcTemplate是两个普通的bean,我们没有告诉它们之间的联系。那不禁要问,jdbcTemplate怎么知道在不在事务中,在哪个transactionTemplate中?我查看了源代码之后得出了结论。每个数据库连接一次只能打开一个事务,所以jdbcTemplate只要获取到transactionTemplate的数据库连接即可,数据库连接自带事务管理。transactionTemplate在开始事务的时候会将当前的数据库连接放入TransactionSynchronizationManager(TSM)中的ThreadLocal中。jdbcTemplate从TSM获取当前的数据库连接,即可提交SQL请求,事务由数据库连接控制,jdbcTemplate无须考虑事务。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章