[笔记迁移][Spring Boot]SQL数据访问[5]

15 篇文章 0 订阅
本文介绍了Spring Boot中如何整合原生JDBC与Druid数据源,以及详细步骤来整合MyBatis,包括全注解和配置文件方式的使用,并提到了如何在控制台显示MyBatis的SQL日志。
摘要由CSDN通过智能技术生成

1. 简介

  1. 对于DAO层,SQL or NoSQL,Spring Boot默认在底层使用 Spring Data 的方式进行统一处理,通过各种xxxTemplate,xxxRepository简化对DAO层的操作。
  2. 与DAO层有关的starter,使用spring-boot-starter-data-{数据交互产品}进行命名如spring-boot-starter-data-jdbc等。

2.整合原生JDBC(需要导入jdbc模块和对应数据库驱动模块)

2.1 简单配置(映射绑定的是DataSourceProperties)
spring:
 datasource:
  driver-class-name: com.mysql.jdbc.Driver
  username: root
  password: sysadmin
  url: jdbc:mysql://localhost:3306/mybatis

效果:默认使用 org.apache.tomcat.jdbc.pool.DataSource

@ConfigurationProperties(
    prefix = "spring.datasource"
)
public class DataSourceProperties implements BeanClassLoaderAware, EnvironmentAware, InitializingBean {
    private ClassLoader classLoader;
    private Environment environment;
    private String name = "testdb";
    private boolean generateUniqueName;
    private Class<? extends DataSource> type;
    private String driverClassName;
    private String url;
    private String username;
    private String password;
    private String jndiName;
    private boolean initialize = true;
    private String platform = "all";
    private List<String> schema;
    private String schemaUsername;
    private String schemaPassword;
    private List<String> data;
    private String dataUsername;
    private String dataPassword;
    private boolean continueOnError = false;
    private String separator = ";";
    private Charset sqlScriptEncoding;
    private EmbeddedDatabaseConnection embeddedDatabaseConnection;
    private DataSourceProperties.Xa xa;
    private String uniqueName;
    //... ...
    }
2.2. 数据源自动配置原理(相关类都在org.springframework.boot.autoconfigure.jdbc下)
  1. 参考DataSourceConfiguration,根据@ConditionalOnClass即导入的依赖情况和@ConditionalOnProperty(spring.datasource.type)来选择创建哪种数据源,默认使用Tomcat连接池。
    (1)Spring Boot默认支持:org.apache.tomcat.jdbc.pool.DataSource/HikariDataSource/BasicDataSource(dbcp和dbcp2)。
    (2)自定义数据源的原理

    @ConditionalOnMissingBean({DataSource.class})
    @ConditionalOnProperty(
        name = {"spring.datasource.type"}
    )
    static class Generic {
        Generic() {
        }
    
        @Bean
        public DataSource dataSource(DataSourceProperties properties) {
           	//建造者模式创建数据源,利用BeanUtil反射创建相应Type的数据源,并绑定相关属性
            return properties.initializeDataSourceBuilder().build();
        }
    }
    
  2. DataSourceAutoConfiguration向容器中添加了一个 DataSourceInitializer
    (implements ApplicationListener),其作用包括:
    (1) runSchemaScripts():应用启动时运行建表语句脚本,这些文件命名模式为schema-*.sql,默认为schema-all.sql。(注意,每次重启时都会删掉同名旧表创建新表。第二次启动前应该删掉这段配置。)

    private void runSchemaScripts() {
        List<Resource> scripts = this.getScripts("spring.datasource.schema", this.properties.getSchema(), "schema");
        if (!scripts.isEmpty()) {
            String username = this.properties.getSchemaUsername();
            String password = this.properties.getSchemaPassword();
            this.runScripts(scripts, username, password);
    
            try {
                this.applicationContext.publishEvent(new DataSourceInitializedEvent(this.dataSource));
                if (!this.initialized) {
                    this.runDataScripts();
                    this.initialized = true;
                }
            } catch (IllegalStateException var5) {
                logger.warn("Could not send event to complete DataSource initialization (" + var5.getMessage() + ")");
            }
        }
    
    private List<Resource> getScripts(String propertyName, List<String> resources, String fallback) {
        if (resources != null) {
            return this.getResources(propertyName, resources, true);
        } else {
            String platform = this.properties.getPlatform();
            List<String> fallbackResources = new ArrayList();
          	//fallback是传递过来的“schema”
          	//private String platform = "all";故schema-all.sql/schema.sql都是默认加载的
            fallbackResources.add("classpath*:" + fallback + "-" + platform + ".sql");
            fallbackResources.add("classpath*:" + fallback + ".sql");
            return this.getResources(propertyName, fallbackResources, false);
        }
    }
    

    (2) runDataScripts():运行插入数据的语句脚本,这些文件命名模式为data-*.sql,默认为data-all.sql。

    private void runDataScripts() {
        List<Resource> scripts = this.getScripts("spring.datasource.data", this.properties.getData(), "data");
        String username = this.properties.getDataUsername();
        String password = this.properties.getDataPassword();
        this.runScripts(scripts, username, password);
    }
    

    (3)如果不想用默认值,可以在配置文件中指定spring: datasource: schema 可以指定自定义sql脚本位置。

    spring:
     datasource:
      #...
      #schema是一个List<String>
      schema:
       - classpath:department.sql
       - classpath:sql/employee.sql
    
  3. JdbcTemplateAutoConfiguration自动配置JdbcTemplate来操作数据库。

3.使用Druid数据源

  1. 在pom.xml中导入Druid依赖。
  2. 在主配置文件中指定数据源type:com.alibaba.druid.pool.DruidDataSouce及其他初始化参数:
    	spring:
    	 datasource:
    	  driver-class-name: com.mysql.jdbc.Driver
    	  username: root
    	  password: sysadmin
    	  url: jdbc:mysql://localhost:3306/mybatis
    	  type: com.alibaba.druid.pool.DruidDataSource
    	  
    	  initialSize: 5
    	  minIdle: 5
    	  maxActive: 20
    	  maxWait: 60000
    	  timeBetweenEvictionRunsMillis: 60000
    	  minEvictableIdleTimeMillis: 300000
    	  validationQuery: SELECT 1 FROM DUAL
    	  testWhileIdle: true
    	  testOnBorrow: false
    	  testOnReturn: false
    	  poolPreparedStatements: true
    
  3. 由于主配置文件中前缀为spring.datasource的配置默认映射绑定的是DataSourceProperties,而其中并没有Druid的相关设置,就无法映射绑定这些属性。 因此,只能手动在配置类@Configuration中通过@Bean注入Druid数据源。
    @Configuration
    public class DruidConfig {
    	
    	//能这样使用@ConfigurationProperties是因为DruidDataSource中声明了这些属性,就能够一一映射绑定。
    	//同时这种用法从另一个角度说明了,只要是注入到容器中的组件,不论是它作为属性、返回值,都可以使用@ConfigurationProperties进行映射绑定。
        @ConfigurationProperties(prefix = "spring.datasource")
        @Bean
        public DataSource druid(){
            return new DruidDataSource();
        }
    
    
  4. 在配置类@Configuration中注入管理后台的Servlet和监控的Filter。
    	    //配置Druid监控
    	    //1. 配置一个管理后台的Servlet(处理进入管理后台的请求)
    	    @Bean
    	    public ServletRegistrationBean  statViewServlet(){
    	        ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(),"/druid/*");
    	        //设置初始化参数
    	        Map<String,String> initParams = new HashMap<>();
    	        initParams.put("loginUsername","admin");
    	        initParams.put("loginPassword","123456");
    	        //不写即允许所有地址访问
    	        initParams.put("allow","localhost");
    	        bean.setInitParameters(initParams);
    	        return bean;
    	    }
    	    
    	    //2.配置一个监控的Filter
    	    @Bean
    	    public FilterRegistrationBean webStatFilter(){
    	        FilterRegistrationBean bean = new FilterRegistrationBean();
    	        bean.setFilter(new WebStatFilter());
    	        //设置初始化参数
    	        Map<String,String> initParams=new HashMap<>();
    	        initParams.put("exclusions","*.js,*.css,/druid/*");
    			bean.setUrlPatterns(Arrays.aslist("/*"));
    		    bean.setInitParameters(initParams);
    	        return bean;
    	    }
    	}
    

4. 整合MyBatis(需要导入对应数据库驱动模块和MyBatis模块)

4.1 mybatis-spring-boot-starter
  1. MyBatis模块的mybatis-spring-boot-starter不是Spring官方出品的,而是MyBatis官方自己对SpringBoot的适配。
    <!--pom.xml-->
    <dependency>
      <groupId>org.mybatis.spring.boot</groupId>
      <artifactId>mybatis-spring-boot-starter</artifactId>
      <version>1.3.2</version>
    </dependency>
    
    由mybatis-spring-boot-starter引入的依赖有spring-boot-starter-jdbc、mybatis(本体包)、mybatis-spring(mybatis与spring的整合包)、mybatis-spring-boot-autoconfigure(自动配置包)。
    MyBatisDependencies
4.2 全注解方式使用MyBatis
  1. 重要注解@Mapper(一个个标注在Mapper接口上)/@MapperScan(一次性标注在配置类上,批量扫描)
    //说明这是一个Mapper,如果没有主配置类/MyBatis配置类上没有标注@MapperScan,则每个Mapper上必须标注@Mapper
    @Mapper
    public interface DepartmentMapper {
    
       @Select("SELECT * FROM tbl_dept WHERE id=#{id}")
       public Department getDeptById(Integer id);
    
       @Delete("DELETE FROM tbl_dept WHERE id=#{id}")
       public Integer deleteDeptById(Integer id);
     
       //获取自增主键。在插入后,主键被封装到参数dept中
       @Options(useGeneratedKeys=true,keyProperty="id")
       @Insert("INSERT INTO tbl_dept(departmentName) values(#{departmentName})")
       public Integer insertDept(Department dept);
       
       @Update("UPDATE tbl_dept SET departmentName=#{departmentName} WHERE id=#{id}")
       public Integer updateDept(Department dept);
    }
    
  2. MyBatis自动配置原理(MyBatisAutoConfiguration+MyBatisProperties)
    @Configuration
    @ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})
    @ConditionalOnBean({DataSource.class})
    @EnableConfigurationProperties({MybatisProperties.class})
    @AutoConfigureAfter({DataSourceAutoConfiguration.class})
    public class MybatisAutoConfiguration {
      //... ...
      private final MybatisProperties properties;
      
        @Bean
        @ConditionalOnMissingBean
        public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
            SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
            factory.setDataSource(dataSource);
            factory.setVfs(SpringBootVFS.class);
            if (StringUtils.hasText(this.properties.getConfigLocation())) {
                factory.setConfigLocation(this.resourceLoader.getResource(this.properties.getConfigLocation()));
            }
    
            org.apache.ibatis.session.Configuration configuration = this.properties.getConfiguration();
            if (configuration == null && !StringUtils.hasText(this.properties.getConfigLocation())) {
                configuration = new org.apache.ibatis.session.Configuration();
            }
    
            if (configuration != null && !CollectionUtils.isEmpty(this.configurationCustomizers)) {
            	//获得容器中所有的ConfigurationCustiomizer,遍历调用其customize方法,获得自定义MyBatis相关设置。
                Iterator var4 = this.configurationCustomizers.iterator();
    
                while(var4.hasNext()) {
                    
                    ConfigurationCustomizer customizer = (ConfigurationCustomizer)var4.next();
                    customizer.customize(configuration);
                }
            }
    
            factory.setConfiguration(configuration);
            if (this.properties.getConfigurationProperties() != null) {
                factory.setConfigurationProperties(this.properties.getConfigurationProperties());
            }
    
            if (!ObjectUtils.isEmpty(this.interceptors)) {
                factory.setPlugins(this.interceptors);
            }
    
            if (this.databaseIdProvider != null) {
                factory.setDatabaseIdProvider(this.databaseIdProvider);
            }
    
            if (StringUtils.hasLength(this.properties.getTypeAliasesPackage())) {
                factory.setTypeAliasesPackage(this.properties.getTypeAliasesPackage());
            }
    
            if (StringUtils.hasLength(this.properties.getTypeHandlersPackage())) {
                factory.setTypeHandlersPackage(this.properties.getTypeHandlersPackage());
            }
    
            if (!ObjectUtils.isEmpty(this.properties.resolveMapperLocations())) {
                factory.setMapperLocations(this.properties.resolveMapperLocations());
            }
    
            return factory.getObject();
        }
      //... ...
    }
    
    //主配置文件中,对MyBatis的所有配置都以mybatis前缀开头。
    @ConfigurationProperties(
        prefix = "mybatis"
    )
    public class MybatisProperties {
        public static final String MYBATIS_PREFIX = "mybatis";
        private String configLocation;
        private String[] mapperLocations;
        private String typeAliasesPackage;
        private String typeHandlersPackage;
        private boolean checkConfigLocation = false;
        private ExecutorType executorType;
        private Properties configurationProperties;
      	//... ...
    }
    
  3. 自定义MyBatis的配置,除了在主配置文件中设置mybatis.xxx外,还可以在配置类中给容器注入一个ConfigurationCustomizer。
    //批量扫描所有Mapper接口
    @MapperScan(value="me.zj.springboot.mapper")	
    @Configuration
    public class MyBatisConfig {
    
        @Bean
        public ConfigurationCustomizer configurationCustomizer(){
            return new ConfigurationCustomizer() {
                @Override
                public void customize(org.apache.ibatis.session.Configuration configuration) {
                  	//驼峰映射
                    configuration.setMapUnderscoreToCamelCase(true);
                }
            };
        }
    
    }
    
4.2 配置文件(MyBatis全局配置文件+Mapper映射文件)方式使用MyBatis
  1. 这种方式同样需要标注@Mapper或@MapperScan。
  2. 与之前的应用只有一点不同需要注意:在主配置文件中指定mybatis.config-location(mybatis的全局配置文件)和mybatis.mapper-locations(mapper与sql的映射文件)。
4.3 全注解与全配置的方式可以结合使用

只要在主配置文件指定mybatis.mapper-locations即可使用配置文件的方式映射Mapper接口,而不是@Select/@Insert/@Update/@Delete等注解。

4.4 要在控制台显示MyBatis的SQL操作日志,只需要在主配置文件中将logging.level.{mapper包的位置}设置为debug即可
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值