springboot工作总结

springboot jdbc

2017-08-08  本文已影响636人  二月_春风

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,这时事务就没有回滚。

上一篇 下一篇

猜你喜欢

热点阅读