1. 程式人生 > 其它 >JdbcTemplate基本使用

JdbcTemplate基本使用

作者:季沐測試筆記
原文地址https://www.cnblogs.com/testero/p/15423024.html
部落格主頁https://www.cnblogs.com/testero

JdbcTemplate基本使用

01-JdbcTemplate基本使用-概述

JdbcTemplate是spring框架中提供的一個物件,是對原始繁瑣的Jdbc API物件的簡單封裝。spring框架為我們提供了很多的操作模板類。例如:操作關係型資料的JdbcTemplate和HibernateTemplate,操作nosql資料庫的RedisTemplate,操作訊息佇列的JmsTemplate等等。

02-JdbcTemplate基本使用-開發步驟

①匯入spring-jdbc和spring-tx座標

②建立資料庫表和實體

③建立JdbcTemplate物件

④執行資料庫操作

03-JdbcTemplate基本使用-快速入門程式碼實現

匯入spring-jdbc和spring-tx座標

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.itheima</groupId>
  <artifactId>itheima_spring_jdbc</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>war</packaging>

  <name>itheima_spring_jdbc Maven Webapp</name>
  <!-- FIXME change it to the project's website -->
  <url>http://www.example.com</url>
  <dependencies>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.32</version>
    </dependency>
    <dependency>
      <groupId>c3p0</groupId>
      <artifactId>c3p0</artifactId>
      <version>0.9.1.2</version>
    </dependency>
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.10</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.0.5.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>5.0.5.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>5.0.5.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.0.5.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.0.1</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>javax.servlet.jsp-api</artifactId>
      <version>2.2.1</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.9.0</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.0</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-annotations</artifactId>
      <version>2.9.0</version>
    </dependency>
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.3.1</version>
    </dependency>
    <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.3</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.0.5.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>5.0.5.RELEASE</version>
    </dependency>
  </dependencies>
</project>

建立資料庫表和實體

package com.itheima.domain;

public class Account {

    private String name;
    private double money;

    public String getNa me() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }

    @Override
    public String toString() {
        return "Account{" +
                "name='" + name + '\'' +
                ", money=" + money +
                '}';
    }
}

建立JdbcTemplate物件

執行資料庫操作

@Test
    //測試JdbcTemplate開發步驟
    public void test1() throws PropertyVetoException {
        //建立資料來源物件
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setDriverClass("com.mysql.jdbc.Driver");
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
        dataSource.setUser("root");
        dataSource.setPassword("root");

        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        //設定資料來源物件  知道資料庫在哪
        jdbcTemplate.setDataSource(dataSource);
        //執行操作
        int row = jdbcTemplate.update("insert into account values(?,?)", "tom", 5000);
        System.out.println(row);

    }

04-JdbcTemplate基本使用-spring產生模板物件分析

我們可以將JdbcTemplate的建立權交給Spring,將資料來源DataSource的建立權也交給Spring,在Spring容器內部將資料來源DataSource注入到JdbcTemplate模版物件中,然後通過Spring容器獲得JdbcTemplate物件來執行操作。

05-JdbcTemplate基本使用-spring產生模板物件程式碼實現

配置如下:

<!--資料來源物件-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql:///test"></property>
        <property name="user" value="root"></property>
        <property name="password" value="root"></property>
    </bean>

    <!--jdbc模板物件-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>

測試程式碼

 @Test
    //測試Spring產生jdbcTemplate物件
    public void test2() throws PropertyVetoException {
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        JdbcTemplate jdbcTemplate = app.getBean(JdbcTemplate.class);
        int row = jdbcTemplate.update("insert into account values(?,?)", "lisi", 5000);
        System.out.println(row);
    }

06-JdbcTemplate基本使用-spring產生模板物件程式碼實現(抽取jdbc.properties)

將資料庫的連線資訊抽取到外部配置檔案中,和spring的配置檔案分離開,有利於後期維護

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/test
jdbc.username=root
jdbc.password=root

配置檔案修改為:

<?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"
       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.xsd
">

    <!--載入jdbc.properties-->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <!--資料來源物件-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

    <!--jdbc模板物件-->
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>

</beans>

07-JdbcTemplate基本使用-常用操作-更新操作

package com.itheima.test;

import com.itheima.domain.Account;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.List;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class JdbcTemplateCRUDTest {

    @Autowired
    private JdbcTemplate jdbcTemplate;
    
	//修改更新
    @Test
    public void testUpdate(){
        jdbcTemplate.update("update account set money=? where name=?",10000,"tom");
    }
	//刪除
    @Test
    public void testDelete(){
        jdbcTemplate.update("delete from account where name=?","tom");
    }

}

08-JdbcTemplate基本使用-常用操作-查詢操作

package com.itheima.test;

import com.itheima.domain.Account;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.List;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class JdbcTemplateCRUDTest {

    @Autowired
    private JdbcTemplate jdbcTemplate;
    
	//聚合查詢
    @Test
    public void testQueryCount(){
        Long count = jdbcTemplate.queryForObject("select count(*) from account", Long.class);
        System.out.println(count);
    }
	//查詢一個
    @Test
    public void testQueryOne(){
        Account account = jdbcTemplate.queryForObject("select * from account where name=?", new BeanPropertyRowMapper<Account>(Account.class), "tom");
        System.out.println(account);
    }
	//查詢所有
    @Test
    public void testQueryAll(){
        List<Account> accountList = jdbcTemplate.query("select * from account", new BeanPropertyRowMapper<Account>(Account.class));
        System.out.println(accountList);
    }

}

09-JdbcTemplate基本使用-知識要點

①匯入spring-jdbc和spring-tx座標

②建立資料庫表和實體

③建立JdbcTemplate物件

		JdbcTemplate jdbcTemplate = newJdbcTemplate();
	       jdbcTemplate.setDataSource(dataSource);

④執行資料庫操作

更新操作:

    jdbcTemplate.update (sql,params)

查詢操作:

    jdbcTemplate.query (sql,Mapper,params)

jdbcTemplate.queryForObject(sql,Mapper,params)

宣告式事務控制

1. 程式設計式事務控制相關物件

1.1 PlatformTransactionManager

PlatformTransactionManager 介面是 spring 的事務管理器,它裡面提供了我們常用的操作事務的方法。

注意:

PlatformTransactionManager 是介面型別,不同的 Dao 層技術則有不同的實現類,例如:Dao 層技術是jdbc 或 mybatis 時:org.springframework.jdbc.datasource.DataSourceTransactionManager

Dao 層技術是hibernate時:org.springframework.orm.hibernate5.HibernateTransactionManager

1.2 TransactionDefinition

TransactionDefinition 是事務的定義資訊物件,裡面有如下方法:

1. 事務隔離級別

設定隔離級別,可以解決事務併發產生的問題,如髒讀、不可重複讀和虛讀。

  • ISOLATION_DEFAULT

  • ISOLATION_READ_UNCOMMITTED

  • ISOLATION_READ_COMMITTED

  • ISOLATION_REPEATABLE_READ

  • ISOLATION_SERIALIZABLE

2. 事務傳播行為

  • REQUIRED:如果當前沒有事務,就新建一個事務,如果已經存在一個事務中,加入到這個事務中。一般的選擇(預設值)

  • SUPPORTS:支援當前事務,如果當前沒有事務,就以非事務方式執行(沒有事務)

  • MANDATORY:使用當前的事務,如果當前沒有事務,就丟擲異常

  • REQUERS_NEW:新建事務,如果當前在事務中,把當前事務掛起。

  • NOT_SUPPORTED:以非事務方式執行操作,如果當前存在事務,就把當前事務掛起

  • NEVER:以非事務方式執行,如果當前存在事務,丟擲異常

  • NESTED:如果當前存在事務,則在巢狀事務內執行。如果當前沒有事務,則執行 REQUIRED 類似的操作

  • 超時時間:預設值是-1,沒有超時限制。如果有,以秒為單位進行設定

  • 是否只讀:建議查詢時設定為只讀

1.3 TransactionStatus

TransactionStatus 介面提供的是事務具體的執行狀態,方法介紹如下。

1.4 知識要點

程式設計式事務控制三大物件

  • PlatformTransactionManager

  • TransactionDefinition

  • TransactionStatus

2 基於 XML 的宣告式事務控制

2.1 什麼是宣告式事務控制

Spring 的宣告式事務顧名思義就是採用宣告的方式來處理事務。這裡所說的宣告,就是指在配置檔案中宣告,用在 Spring 配置檔案中宣告式的處理事務來代替程式碼式的處理事務。

宣告式事務處理的作用

  • 事務管理不侵入開發的元件。具體來說,業務邏輯物件就不會意識到正在事務管理之中,事實上也應該如此,因為事務管理是屬於系統層面的服務,而不是業務邏輯的一部分,如果想要改變事務管理策劃的話,也只需要在定義檔案中重新配置即可

  • 在不需要事務管理的時候,只要在設定檔案上修改一下,即可移去事務管理服務,無需改變程式碼重新編譯,這樣維護起來極其方便

注意:Spring 宣告式事務控制底層就是AOP。

2.2 宣告式事務控制的實現

宣告式事務控制明確事項:

  • 誰是切點?

  • 誰是通知?

  • 配置切面?

①引入tx名稱空間

<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/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">


②配置事務增強

<!--平臺事務管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"></property>
</bean>

<!--事務增強配置-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="*"/>
    </tx:attributes>
</tx:advice>

③配置事務 AOP 織入

<!--事務的aop增強-->
<aop:config>
    <aop:pointcut id="myPointcut" expression="execution(* com.itheima.service.impl.*.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="myPointcut"></aop:advisor>
</aop:config>

④測試事務控制轉賬業務程式碼

@Override
public void transfer(String outMan, String inMan, double money) {
    accountDao.out(outMan,money);
    int i = 1/0;
    accountDao.in(inMan,money);
}

2.3 切點方法的事務引數的配置

<!--事務增強配置-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="*"/>
    </tx:attributes>
</tx:advice>

其中,tx:method 代表切點方法的事務引數的配置,例如:

<tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED" timeout="-1" read-only="false"/>
  • name:切點方法名稱

  • isolation:事務的隔離級別

  • propogation:事務的傳播行為

  • timeout:超時時間

  • read-only:是否只讀

2.4 知識要點

宣告式事務控制的配置要點

  • 平臺事務管理器配置

  • 事務通知的配置

  • 事務aop織入的配置

3 基於註解的宣告式事務控制

3.1 使用註解配置宣告式事務控制

  1. 編寫 AccoutDao
@Repository("accountDao")
public class AccountDaoImpl implements AccountDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;
    public void out(String outMan, double money) {
        jdbcTemplate.update("update account set money=money-? where name=?",money,outMan);
    }
    public void in(String inMan, double money) {
        jdbcTemplate.update("update account set money=money+? where name=?",money,inMan);
    }
}
  1. 編寫 AccoutService
@Service("accountService")
@Transactional
public class AccountServiceImpl implements AccountService {
    @Autowired
    private AccountDao accountDao;
    @Transactional(isolation = Isolation.READ_COMMITTED,propagation = Propagation.REQUIRED)
    public void transfer(String outMan, String inMan, double money) {
        accountDao.out(outMan,money);
        int i = 1/0;
        accountDao.in(inMan,money);
    }
}
  1. 編寫 applicationContext.xml 配置檔案
<!—之前省略datsSource、jdbcTemplate、平臺事務管理器的配置-->
<!--元件掃描-->
<context:component-scan base-package="com.itheima"/>
<!--事務的註解驅動-->
<tx:annotation-driven/>

3.2 註解配置宣告式事務控制解析

①使用 @Transactional 在需要進行事務控制的類或是方法上修飾,註解可用的屬性同 xml 配置方式,例如隔離級別、傳播行為等。

②註解使用在類上,那麼該類下的所有方法都使用同一套註解引數配置。

③使用在方法上,不同的方法可以採用不同的事務引數配置。

④Xml配置檔案中要開啟事務的註解驅動<tx:annotation-driven />

3.3 知識要點

註解宣告式事務控制的配置要點

  • 平臺事務管理器配置(xml方式)

  • 事務通知的配置(@Transactional註解配置)

  • 事務註解驅動的配置 tx:annotation-driven/