纯手写SpringBoot教案系列-SpringBoot-数据访问详解

四.SpringBoot 数据访问

1.简介

SpringBoot底层采用了Spring Data框架操作数据

2. JDBC

  1. 使用Spring Initializer创建项目

  2. 选中Web,Mysql,JDBC模块并生成项目

  3. 生成的项目不能直接运行,因为我们导入了数据库相关的依赖,必须配置数据库才能正常启动

  4. 配置数据库相关

    #spring配置
    spring:
      #数据库相关
      datasource:
        url: jdbc:mysql:///live?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
        username: huanqwer
        password: zhz521
        driverClassName: com.mysql.cj.jdbc.Driver
    
  5. 如果没有指定自己的数据源,SpringBoot官方默认使用Tomcat连接池作为我们的数据源,我们也可以用spring.datasource.type指定我们自己的数据源(c3p0,dbcp,Druid等)

  6. Tomcat连接池简单的配置示例

    #spring配置
    spring:
      #数据库相关
      datasource:
        url: jdbc:mysql:///live?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
        username: huanqwer
        password: zhz521
        driverClassName: com.mysql.cj.jdbc.Driver
        max-active: 20
        max-idle: 8
        min-idle: 8
        initial-size: 20
    

3. 整合自己的数据源

整合阿里的Druid数据源

  1. 去Maven Repo上找到最新版的Druid依赖

    <!--druid -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.19</version>
    </dependency>
    
  2. 引入后我们的项目会报错,无法启动,是因为数据源没有切换过来

  3. 我们使用type指定DruidDataSource

  4. 找到Druid引入包下面的DataSource

在这里插入图片描述

  1. 引入后的yml如下

    #系统端口
    server:
      port: 80
    
    #spring配置
    spring:
      #数据库相关
      datasource:
        url: jdbc:mysql:///live?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC
        username: huanqwer
        password: zhz521
        driverClassName: com.mysql.cj.jdbc.Driver
        type: com.alibaba.druid.pool.DruidDataSource
    
    #全站配置
    site:
      url : localhost
      updatePath : update
      suId : '0033081800192'
      drId : '0024062400084'
      smsDeadTime : 5
      smsNum: 5
    
    
    
  2. 运行后切换数据源成功!

  3. 对数据源进行配置

    参考文献,只参考配置部分(文档中的filters配置是错误的,需要定义为数组)

    https://blog.csdn.net/weixin_43453386/article/details/83582399

    # 初始化连接池个数
    initialSize: 5
    # 最小连接池个数——》已经不再使用,配置了也没效果
    minIdle: 2
    # 最大连接池个数
    maxActive: 20
    # 配置获取连接等待超时的时间,单位毫秒,缺省启用公平锁,并发效率会有所下降
    maxWait: 60000
    # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
    timeBetweenEvictionRunsMillis: 60000
    # 配置一个连接在池中最小生存的时间,单位是毫秒
    minEvictableIdleTimeMillis: 300000
    # 用来检测连接是否有效的sql,要求是一个查询语句。
    # 如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用
    validationQuery: SELECT 1 FROM DUAL
    # 建议配置为true,不影响性能,并且保证安全性。
    # 申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
    testWhileIdle: true
    # 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
    testOnBorrow: false
    # 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
    testOnReturn: false
    # 打开PSCache,并且指定每个连接上PSCache的大小
    poolPreparedStatements: true
    maxPoolPreparedStatementPerConnectionSize: 20
    # 通过别名的方式配置扩展插件,多个英文逗号分隔,常用的插件有: 
    # 监控统计用的filter:stat
    # 日志用的filter:log4j
    # 防御sql注入的filter:wall
    filters: [stat,wall,log4j]
    # 通过connectProperties属性来打开mergeSql功能;慢SQL记录
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
    # 合并多个DruidDataSource的监控数据
    useGlobalDataSourceStat: true
    

    配置后并不会生效

    因为默认不会识别,需要对应的配置类(没有参考文章里的,用我们之前的知识配置)

    @Configuration
    public class DruidConfig {
    
        @ConfigurationProperties(prefix = "spring.datasource")
        @Bean
        public DataSource druid(){
            return new DruidDataSource();
        }
    }
    

    然后在测试类中测试我们的配置是否生效

在这里插入图片描述

可见我们数据源已经替换成功

在数据源上打断点,查看配置详情

在这里插入图片描述

以debug模式运行

在这里插入图片描述

选择dataSource并查看对象属性

在这里插入图片描述

可见我们的配置已经被读取

在这里插入图片描述

  1. 配置Druid监控(参考CSDN文献)

     /**
         *  主要实现WEB监控的配置处理
         */
        @Bean
        public ServletRegistrationBean druidServlet() {
            // 现在要进行druid监控的配置处理操作
            ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(
                    new StatViewServlet(), "/druid/*");
            // 白名单,多个用逗号分割, 如果allow没有配置或者为空,则允许所有访问
            servletRegistrationBean.addInitParameter("allow", "127.0.0.1,172.29.32.54");
            // 黑名单,多个用逗号分割 (共同存在时,deny优先于allow)
            servletRegistrationBean.addInitParameter("deny", "192.168.1.110");
            // 控制台管理用户名
            servletRegistrationBean.addInitParameter("loginUsername", "admin");
            // 控制台管理密码
            servletRegistrationBean.addInitParameter("loginPassword", "admin");
            // 是否可以重置数据源,禁用HTML页面上的“Reset All”功能
            servletRegistrationBean.addInitParameter("resetEnable", "false");
            return servletRegistrationBean ;
        }
        
        @Bean
        public FilterRegistrationBean filterRegistrationBean() {
            FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean() ;
            filterRegistrationBean.setFilter(new WebStatFilter());
            //所有请求进行监控处理
            filterRegistrationBean.addUrlPatterns("/*"); 
            //添加不需要忽略的格式信息
            filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.css,/druid/*");
            return filterRegistrationBean ;
        }
    
  2. 访问http://localhost/druid,用户名admin密码admin,进入后台监控

4. 整合Mybatis

  1. 重新创建项目,选择模块:web,lombok,dev-tools,processor,Mysql,JDBC,MyBatis

  2. 引入Druid(或者使用默认Tomcat连接池)

  3. 配置Druid

  4. 项目自动创建表

    spring:
    	datasource:
    		schema:
    			- classpath:sql/{tablename}.sql
    			- classpath:sql/{tablename}.sql
    

    项目启动后会自动跑sql语句创建表

    注意:第二次运行时要把schema注掉!

4.1 注解版Mybatis

  1. 创建Mapper文件

    @Mapper
    public interface BaseMapper {
    
        @Select("select * from user where u_gyh = #{gyh}")
        List<Map<String, Object>> getUserByGyh(String gyh);
    
    }
    
    

    或者可以根据参数的顺序

    @Mapper
    public interface BaseMapper {
    
        @Select("select * from user where u_gyh = #{arg0}")
        List<Map<String, Object>> getUserByGyh(String gyh);
    
    }
    
    
  2. 注解版插入后id为NULL

    使用@Options注解

    @Options(useGeneratedKeys = true,keyProperty = "id")
    
    
  3. 注解版开启批量别名定义

    以前我们可以直接在xml中使用type_alias批量定义别名

    但是在注解版里怎么配置呢?

    @Configuration
    public class MybatisConfig {
    
        @Bean
        public ConfigurationCustomizer configurationCustomizer(){
            return new ConfigurationCustomizer() {
                @Override
                public void customize(org.apache.ibatis.session.Configuration configuration) {
                    configuration.setMapUnderscoreToCamelCase(true);
                }
            };
        }
    }
    
    

    同样,咱们可以在yml中直接配置

    #mybatis驼峰命名
    mybatis:
      configuration:
        map-underscore-to-camel-case: true
    
    
  4. 每个类加@Mapper注解太麻烦

    在主程序上加@MapperScan

    @SpringBootApplication
    @MapperScan("com.scj.mana.mapper")
    public class ManaApplication {
    
        public static void main(String[] args) {
            SpringApplication app = new SpringApplication(ManaApplication.class);
            app.setBannerMode(Banner.Mode.OFF);
            app.run(args);
        }
    
    }
    
    
  5. 创建对应实体太麻烦

    可以使用Mybatis逆向工程为我们生成pojos,但是逆向工程师用于生成xml,所以接下来我们讲解配置版的Mybatis

4.2 配置版的Mybatis(略,放到后面讲)

  1. 添加逆向工程依赖

    上maven repo上找到mybatis逆向工程依赖

     <!--mybatis-generator-core -->
    <dependency>
        <groupId>org.mybatis.generator</groupId>
        <artifactId>mybatis-generator-core</artifactId>
        <version>1.3.7</version>
    </dependency>
    
    

    等待下载完成后在resources文件夹下创建逆向工程配置文件

    巴拉巴拉…

4.3 整合Mybatis最佳实践

全注解开发中我们会发现在写insert语句会特别耗费时间

所以我们使用navicat中添加任意一条数据,然后赋值为insert语句

INSERT INTO `live`.`user`(`u_id`, `u_gyh`, `u_mobile`, `u_name`, `user_role`) VALUES (1, '0033081800192', '18641155202', '覃岭', NULL);

在此基础上修改也能降低出错概率

update同理

UPDATE `live`.`user` SET `u_gyh` = '0033081800192', `u_mobile` = '18641155202', `u_name` = '覃岭', `user_role` = NULL WHERE `u_id` = 1;

使用IDEA工具为我们逆向生成实体类

参考文献

https://blog.csdn.net/qq_27435059/article/details/52494623

如果找不到Persistance,我们可以选择项目后按F4,然后点击Modules>点击+号>选择JPA

记住务必下载驱动连接数据库!

生成的代码如下

@Entity
public class User {
    private int uId;
    private String uGyh;
    private String uMobile;
    private String uName;
    private Integer userRole;

    @Id
    @Column(name = "u_id")
    public int getuId() {
        return uId;
    }

    public void setuId(int uId) {
        this.uId = uId;
    }

    @Basic
    @Column(name = "u_gyh")
    public String getuGyh() {
        return uGyh;
    }

    public void setuGyh(String uGyh) {
        this.uGyh = uGyh;
    }

    @Basic
    @Column(name = "u_mobile")
    public String getuMobile() {
        return uMobile;
    }

    public void setuMobile(String uMobile) {
        this.uMobile = uMobile;
    }

    @Basic
    @Column(name = "u_name")
    public String getuName() {
        return uName;
    }

    public void setuName(String uName) {
        this.uName = uName;
    }

    @Basic
    @Column(name = "user_role")
    public Integer getUserRole() {
        return userRole;
    }

    public void setUserRole(Integer userRole) {
        this.userRole = userRole;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return uId == user.uId &&
                Objects.equals(uGyh, user.uGyh) &&
                Objects.equals(uMobile, user.uMobile) &&
                Objects.equals(uName, user.uName) &&
                Objects.equals(userRole, user.userRole);
    }

    @Override
    public int hashCode() {
        return Objects.hash(uId, uGyh, uMobile, uName, userRole);
    }
}

因为我们有lombok

所以修改实体类的代码为

@Data
public class User {
    private int uId;
    private String uGyh;
    private String uMobile;
    private String uName;
    private Integer userRole;
    
}

以上就是整个数据访问内容


以上博文是我在培训的时候整理的教案,码字不易,转载请注明出处,联系邮箱[email protected]

发布了37 篇原创文章 · 获赞 35 · 访问量 6543

猜你喜欢

转载自blog.csdn.net/itkfdektxa/article/details/100126050