1. 程式人生 > >Spring+JDBC組合開發

Spring+JDBC組合開發

mark public image eclipse 註解 需要 比較 setname ram

搭建和配置Spring與JDBC整合的環境

使用Spring+JDBC集成步驟如下:
第一步,配置數據源。我們使用DBCP數據庫連接池。
我們首先在Eclipse中新建一個普通的Java Project,名稱為springAndJDBC。接著導入所需Jar包到項目中,所需Jar包共有:
技術分享
然後我們在Sping配置文件中——beans.xml配置數據源,即在beans.xml中加入如下內容:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
    destroy-method="close">
    <property name="driverClassName" value="com.mysql.jdbc.Driver" />
    <property name="url"
        value="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&amp;characterEncoding=UTF-8" />
    <property name="username" value="root" />
    <property name="password" value="yezi" />
    <!-- 連接池啟動時的初始值 -->
    <property name="initialSize" value="1" />
    <!-- 連接池的最大值 -->
    <property name="maxActive" value="500" />
    <!-- 最大空閑值。當經過一個高峰時間後,連接池可以慢慢將已經用不到的連接慢慢釋放一部分,一直減少到maxIdle為止 -->
    <property name="maxIdle" value="2" />
    <!-- 最小空閑值。當空閑的連接數少於閥值時,連接池就會預申請去一些連接,以免洪峰來時來不及申請 -->
    <property name="minIdle" value="1" />
</bean>
  • 1

第二步,配置事務。因為我們打算使用Spring給我們提供的容器來管理事務。配置事務時,需要在XML配置文件中引入用於聲明事務的tx命名空間,事務的配置方式有兩種:註解方式和基於XML配置方式
我們首先在Spring配置文件中引入用於聲明事務的tx命名空間:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.2.xsd
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">

</beans>
  • 1

接著我們采用註解方式配置聲明式事務,需要在Spring配置文件中添加如下內容:

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

以上配置指定了Spring的事務管理器(由於我們打算使用Spring的事務管理功能),這樣,我們不再手工控制事務的打開、提交或回滾,而是都交給Spring的事務管理器來管理。

提示:org.springframework.jdbc.datasource.DataSourceTransactionManager是Spring為我們提供的專門針對數據源的事務管理器。
由於我們采用註解——@Transactional的方式來配置聲明式事務,所以我們還要在Spring配置文件中添加如下內容:

<tx:annotation-driven transaction-manager="txManager" />

以上配置隱式地註冊了對註解——@Transactional進行解析的處理器。經過以上兩步,Spring與JDBC整合的環境就算搭建好了,Spring配置文件——beans.xml的內容為:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.2.xsd
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url"
            value="jdbc:mysql://localhost:3306/jdbc?useUnicode=true&amp;characterEncoding=UTF-8" />
        <property name="username" value="root" />
        <property name="password" value="yezi" />
        <!-- 連接池啟動時的初始值 -->
        <property name="initialSize" value="1" />
        <!-- 連接池的最大值 -->
        <property name="maxActive" value="500" />
        <!-- 最大空閑值。當經過一個高峰時間後,連接池可以慢慢將已經用不到的連接慢慢釋放一部分,一直減少到maxIdle為止 -->
        <property name="maxIdle" value="2" />
        <!-- 最小空閑值。當空閑的連接數少於閥值時,連接池就會預申請去一些連接,以免洪峰來時來不及申請 -->
        <property name="minIdle" value="1" />
    </bean>

    <bean id="txManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>
    <tx:annotation-driven transaction-manager="txManager" />
</beans>
  • 1

Spring集成的JDBC編碼和事務管理

Spring與JDBC整合的環境搭建好之後,我們就要編寫JDBC代碼了。首先在jdbc數據庫中創建一張person表,如下:
技術分享
接著在src目錄下新建一個cn.itcast.bean包,並在該包下新建一個JavaBean——Person.java,其代碼為:

public class Person {
    private Integer id;
    private String name;

    public Person() {}

    public Person(String name) {
        this.name = name;
    }

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

再接著在src目錄下新建一個cn.itcast.service包,並在該包下新建一個接口——PersonService.java,其代碼為:

public interface PersonService {
    /**
     * 保存person
     */
    public void save(Person person);

    /**
     * 更新person
     */
    public void update(Person person);

    /**
     * 獲取person
     */
    public Person getPerson(Integer personid);

    /**
     * 獲取所有person
     */
    public List<Person> getPersons();

    /**
     * 刪除指定id的person
     */
    public void delete(Integer personid);
}
  • 1

緊接著在src目錄下新建一個cn.itcast.service.impl包,並在該包下新建一個PersonService接口的實現類——PersonServiceBean.java。因為我們要對數據庫person表進行增刪改查,所以需要通過數據源dataSource進行操作,但是我們最好不要直接通過數據源dataSource進行操作,而是應使用Spring為我們提供的JdbcTemplate類進行JDBC操作,因為這個輔助類封裝了比較多的JDBC代碼,故PersonServiceBean類的代碼應為:

/**
 * 使用JdbcTemplate進行insert/update/delete/select操作
 * @author li ayun
 *
 */
public class PersonServiceBean implements PersonService {
    private JdbcTemplate jdbcTemplate;

    public void setDataSource(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    @Override
    public void save(Person person) {
        jdbcTemplate.update("insert into person(name) value(?)", new Object[]{person.getName()}, 
                new int[]{java.sql.Types.VARCHAR});
    }

    @Override
    public void update(Person person) {
        jdbcTemplate.update("update person set name=? where id=?", new Object[]{person.getName(), person.getId()}, 
                new int[]{java.sql.Types.VARCHAR, java.sql.Types.INTEGER});
    }

    /**
     * 使用JdbcTemplate獲取一條記錄
     */
    @Override
    public Person getPerson(Integer personid) {
        return jdbcTemplate.queryForObject("select * from person where id=?", new Object[]{personid}, 
                new int[]{java.sql.Types.INTEGER}, new PeronRowMapper());
    }

    /**
     * 使用JdbcTemplate獲取多條記錄
     */
    @Override
    public List<Person> getPersons() {
        return jdbcTemplate.query("select * from person", new PeronRowMapper());
    }

    @Override
    public void delete(Integer personid) {
        jdbcTemplate.update("delete from person where id=?", new Object[]{personid}, 
                new int[]{java.sql.Types.INTEGER});
    }

}

接下來還要在cn.itcast.service.impl包下新建一個類——PeronRowMapper.java,其代碼為:

public class PeronRowMapper implements RowMapper<Person> {

    @Override
    public Person mapRow(ResultSet rs, int index) throws SQLException {
        Person person = new Person(rs.getString("name"));
        person.setId(rs.getInt("id"));
        return person;
    }

}
  • 1

有人可能會問,為何mapRow()方法內部一開始不調用一下rs.next()方法?答案是外部調用mapRow()方法時,已經執行了諸如if(rs.next()) { ... } 這樣的代碼。
然後我們要將PersonServiceBean交給Spring進行管理,即需要在Spring配置文件中添加如下內容:

<bean id="personService" class="cn.itcast.service.impl.PersonServiceBean">
    <property name="dataSource" ref="dataSource" />
</bean>

最後,我們就要在src目錄下新建一個junit.test包,並在該包下新建一個單元測試類——PersonServiceTest.java,對我們編寫的業務bean的JDBC代碼進行測試。

public class PersonServiceTest {
    private static PersonService personService;

    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
        try {
            ApplicationContext cxt = new ClassPathXmlApplicationContext("beans.xml");
            personService = (PersonService) cxt.getBean("personService");
        } catch (Exception e) { // 若出錯,則打印在控制臺上
            e.printStackTrace();
        }
    }

    @Test
    public void save() {
        personService.save(new Person("李阿昀"));
    }

    @Test
    public void getPerson() {
        Person person = personService.getPerson(1);
        System.out.println(person.getName());
    }

    @Test
    public void update() {
        Person person = personService.getPerson(1);
        person.setName("李子");
        personService.update(person);
    }

    @Test
    public void delete() {
        personService.delete(1);
    }

    @Test
    public void save_5() {
        for (int i = 1; i <= 5; i++) {
            personService.save(new Person("李阿昀" + i));
        }
    }

    @Test
    public void getBeans() {
        for (Person person : personService.getPersons()) {
            System.out.println(person.getName());
        }
    }
}
  • 1

分別測試以上方法,都順利通過,大發!
從PersonServiceBean類的代碼中我們可以看出該PersonServiceBean並沒有受Spring的事務管理,[email protected],[email protected],那麽像save()方法中的每條sql語句都會在各自的事務中進行執行。若save()方法中有2條語句,例如:

public void save(Person person) {
    jdbcTemplate.update("insert into person(name) value(?)", new Object[]{person.getName()}, 
            new int[]{java.sql.Types.VARCHAR});     

    jdbcTemplate.update("insert into person(name) value(?)", new Object[]{person.getName()}, 
            new int[]{java.sql.Types.VARCHAR});
}
  • 1

這樣,2條語句都會在各自的事務中執行,他們是無法保證在同一個事務中執行的,從而會出現一些問題。因此為了保證多條語句在同一個事務中執行,我們應該使用Spring容器給我們提供的聲明式事務,[email protected],[email protected]事務,方法執行後關閉事務。
使用屬性占位符方式配置數據源
在使用Spring+JDBC組合開發過程中,有人喜歡把數據庫連接等信息放在一個屬性文件中,接著使用屬性占位符方式將屬性文件中的內容引用進來。
現在類路徑底下新建一個屬性文件——jdbc.properties,其內容為:
技術分享
接著,我們就要將Spring的配置文件修改為:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.2.xsd
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx-4.2.xsd">

    <context:property-placeholder location="classpath:jdbc.properties" /> <!-- classpath: 明確指明jdbc.properties文件是在類路徑底下的 -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close">
        <property name="driverClassName" value="${jdbc.driverClassName}" />
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}" />
        <property name="password" value="${jdbc.password}" />
        <!-- 連接池啟動時的初始值 -->
        <property name="initialSize" value="${jdbc.initialSize}" />
        <!-- 連接池的最大值 -->
        <property name="maxActive" value="${jdbc.maxActive}" />
        <!-- 最大空閑值。當經過一個高峰時間後,連接池可以慢慢將已經用不到的連接慢慢釋放一部分,一直減少到maxIdle為止 -->
        <property name="maxIdle" value="${jdbc.maxIdle}" />
        <!-- 最小空閑值。當空閑的連接數少於閥值時,連接池就會預申請去一些連接,以免洪峰來時來不及申請 -->
        <property name="minIdle" value="${jdbc.minIdle}" />
    </bean>

    <bean id="txManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>
    <tx:annotation-driven transaction-manager="txManager" />

    <bean id="personService" class="cn.itcast.service.impl.PersonServiceBean">
        <property name="dataSource" ref="dataSource" />
    </bean>
</beans>

此時再來測試PersonServiceTest類中的各個方法,仍然都會順利通過。如須查看源碼,可點擊Spring+JDBC組合開發進行下載。

Spring+JDBC組合開發