springboot jdbc

SpringbootJDBC主要給我們提供了三個功能,第一個就是對數據源的裝配,第二個就是提供一個JDBCTemplte簡化我們的使用,第三個就是事務。

看個demo,加入數據庫驅動,和spring-boot-starter-jdbc依賴:

<dependencies>
    <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
     </dependency>
     <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-jdbc</artifactId>
     </dependency>
</dependencies>

配置數據庫連接:

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test
spring.datasource.username=root
spring.datasource.password=root

以上步驟springboot會自動裝配數據源DataSource和JDBC工具了JdbcTemplate

啟動類:

package com.zhihao.miao;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;
import java.sql.Connection;

@SpringBootApplication
public class Application {
    public static void main(String[] args) throws Exception{
        ConfigurableApplicationContext context = SpringApplication.run(Application.class,args);
        DataSource ds = context.getBean(DataSource.class);
        System.out.println(ds.getClass().getName()); //默認的使用的是tomcat的數據源
        Connection connection = ds.getConnection();
        System.out.println(connection.getCatalog()); //test
        System.out.println(context.getBean(JdbcTemplate.class));
        connection.close();

    }
}

啟動打印:

發現加入數據庫驅動,和spring-boot-starter-jdbc依賴和配置了數據庫的信息之后自動裝配的是org.apache.tomcat.jdbc.pool.DataSource。也主動裝配了JdbcTemplate這個類。

那么springboot默認支持哪些數據源呢?可以看DataSourceAutoConfiguration源碼,


默認支持tomcat-jdbcHikaridbcpdbcp2Generic這五種數據源。那么怎么裝配這些數據源呢?因為我們知道springboot在默認情況下裝配的是tomcat-jdbc數據源,比如我們自己配置一個Hikari數據源。

配置方式有二種,第一種是加入相關數據源的依賴,并且排除tomcat的數據源依賴,

   <dependencies>
     <dependency>
          <groupId>com.zaxxer</groupId>
          <artifactId>HikariCP</artifactId>
      </dependency>
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
      </dependency>
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-jdbc</artifactId>
          <exclusions>
              <exclusion>
                  <groupId>org.apache.tomcat</groupId>
                  <artifactId>tomcat-jdbc</artifactId>
              </exclusion>
          </exclusions>
      </dependency>
</dependencies>

第二種就是加入相關數據源依賴并在配置文件指定默認的數據源,

<dependencies>
     <dependency>
          <groupId>com.zaxxer</groupId>
          <artifactId>HikariCP</artifactId>
      </dependency>
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
      </dependency>
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-jdbc</artifactId>
      </dependency>
</dependencies>

在application.properties中指定數據源:

spring.datasource.type=com.zaxxer.hikari.HikariDataSource

對于springboot默認支持的五種數據源,我們只要將其依賴加入并且進行排除默認的tomcat數據源(或者使用配置文件,如上圖所示就能使用自己的數據源了),那么如果使用springboot默認不支持的數據源呢,比如阿里的druid數據源

也有二種方式,第一種直接加入依賴,并在配置文件中指定數據源類型

  <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.14</version>
   </dependency>

application.properties

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource

第二種方式也是加入相應的數據源依賴,

  <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.0.14</version>
   </dependency>

修改啟動類:

@SpringBootApplication
public class Application {

    @Autowired
    private Environment environment;

    @Bean
    public DataSource dataSource(){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(environment.getProperty("spring.datasource.driver-class-name"));
        dataSource.setUrl(environment.getProperty("spring.datasource.url"));
        dataSource.setUsername(environment.getProperty("spring.datasource.username"));
        dataSource.setPassword(environment.getProperty("spring.datasource.password"));
        return dataSource;
    }


    public static void main(String[] args) throws Exception{
        ConfigurableApplicationContext context = SpringApplication.run(Application.class,args);
        DataSource ds = context.getBean(DataSource.class);
        System.out.println(ds.getClass().getName()); //默認的使用的是tomcat的數據源
        Connection connection = ds.getConnection();
        System.out.println(connection.getCatalog()); //test
        System.out.println(context.getBean(JdbcTemplate.class));
        connection.close();

    }
}

推薦第二種方式,因為可以定制一些數據源的一些其他信息比如初始化連接,最大連接數,最小連接數等等。

Springboot JDBC的事務

事務:

  • 要使用@EnableTransactionManagement啟用對事務的支持
  • 在需要使用事務的方法上面加上@Transactional
    注意,默認只會對運行時異常進行事務回滾,非運行時異常不會回滾事務。

下面我發現不加@EnableTransactionManagement這個注解事務也是生效的

看一個demo:
定義Controller,

@RestController
public class GoodController {

    @Autowired
    private GoodService goodService;

    @PostMapping("/addGood")
    public String addGood(@RequestBody Map<String,List<Good>> map){
        List<Good> goodsList = map.get("goodslist");
        try {
            goodService.addGood(goodsList);
            return "addGood success";
        } catch (Exception e) {
            return "addGood fail";
        }
    }
}

定義Service層及其實現,

public interface GoodService {

    void addGood(List<Good> goodslist) throws Exception;
}
@Service("goodService")
public class GoodServiceImpl implements GoodService{

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public void addGood(List<Good> goodslist) throws Exception{
        for (int i = 0; i < goodslist.size(); i++) {
            Good good = goodslist.get(i);
            String sql = "insert into tb_good (good_id,good_name) values" +
                    "('"+good.getGoodId()+"','"+good.getGoodName()+"')";
            logger.info(sql);
            jdbcTemplate.execute(sql);
        }

    }

}

啟動執行測試,執行成功數據庫中增加了三條記錄

修改代碼,人為的在增加第二條記錄的時候拋出異常,刪除上面的三條數據,

@Service("goodService")
public class GoodServiceImpl implements GoodService{

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Transactional
    public void addGood(List<Good> goodslist) throws Exception{
        for (int i = 0; i < goodslist.size(); i++) {
            Good good = goodslist.get(i);
            String sql = "insert into tb_good (good_id,good_name) values" +
                    "('"+good.getGoodId()+"','"+good.getGoodName()+"')";
            logger.info(sql);
            if("書籍".equals(good.getGoodName())){
                throw new NullPointerException("");
            }
            jdbcTemplate.execute(sql);
        }

    }

}

再去測試,發現事務生效,我們都知道默認事務回滾運行期異常,我們修改代碼,人為的拋出非運行期異常,發現事務并沒有回滾,

@Service("goodService")
public class GoodServiceImpl implements GoodService{

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Transactional
    public void addGood(List<Good> goodslist) throws Exception{
        for (int i = 0; i < goodslist.size(); i++) {
            Good good = goodslist.get(i);
            String sql = "insert into tb_good (good_id,good_name) values" +
                    "('"+good.getGoodId()+"','"+good.getGoodName()+"')";
            logger.info(sql);
            if("書籍".equals(good.getGoodName())){
                throw new FileNotFoundException("");
            }
            jdbcTemplate.execute(sql);
        }

    }
}

那么要使得非運行期異常也回滾,就要使用@Transactional進行相關配置,比如@Transactional(rollbackFor=Exception.class)對所有異常進行回滾不管是運行期還是非運行期異常。

@Service("goodService")
public class GoodServiceImpl implements GoodService{

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Transactional(rollbackFor=Exception.class)
    public void addGood(List<Good> goodslist) throws Exception{
        for (int i = 0; i < goodslist.size(); i++) {
            Good good = goodslist.get(i);
            String sql = "insert into tb_good (good_id,good_name) values" +
                    "('"+good.getGoodId()+"','"+good.getGoodName()+"')";
            logger.info(sql);
            if("書籍".equals(good.getGoodName())){
                throw new FileNotFoundException("");
            }
            jdbcTemplate.execute(sql);
        }

    }

}

還可以通過transactionManager對哪些數據源進行回滾(多數據源情況下),propagation配置事務的傳播行為,isolation配置事務的隔離級別,timeout事務的超時時間,noRollbackForClassName哪些數據可以不回滾等等。

修改代碼
@Service("goodService")
public class GoodServiceImpl implements GoodService{

private Logger logger = LoggerFactory.getLogger(getClass());

@Autowired
private JdbcTemplate jdbcTemplate;


public void addGood(List<Good> goodslist) throws Exception{
    addGoodreal(goodslist);

}

@Transactional
public void addGoodreal(List<Good> goodslist) throws Exception{
    for (int i = 0; i < goodslist.size(); i++) {
        Good good = goodslist.get(i);
        String sql = "insert into tb_good (good_id,good_name) values" +
                "('"+good.getGoodId()+"','"+good.getGoodName()+"')";
        logger.info(sql);
        if("書籍".equals(good.getGoodName())){
            throw new NullPointerException("");
        }
        jdbcTemplate.execute(sql);
    }

}

}

在我們controller層調用addGood的方法上沒有加 @Transactional,這時事務就沒有回滾。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 這部分的參考文檔涉及數據訪問和數據訪問層和業務或服務層之間的交互。 Spring的綜合事務管理支持覆蓋很多細節,然...
    竹天亮閱讀 1,053評論 0 0
  • Spring Boot 參考指南 介紹 轉載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,970評論 6 342
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,981評論 19 139
  • 目錄 4.1李白——《清平調三首》 4.2元稹——《離思》 4.3王陽明——《泛海》 4.4詩經——《子衿》 4....
    翟偉閱讀 524評論 0 0
  • 今天也是有點忙碌,一直到現在才有時間來點滴,可以安靜下來寫寫東西。整理這一天的內心活動,覺察每個環節自己情緒的波動...
    效艷一畝田閱讀 322評論 0 3