1. 程式人生 > >Spring框架:Spring與持久化

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無須考慮事務。