Springboot——数据访问

Springboot——数据访问,第1张

一、SQL 1. 数据源的自动配置

数据源重在连接,配置连接属性,而连接池是数据源内实现的,也是为了高效连接而存在

1.1 导入JDBC场景
  • 首先导入JDBC场景
<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-data-jdbcartifactId>
dependency>

会根据依赖自动导入数据源、jdbc以及事务

  • 导入数据库驱动

选择要导入的数据库驱动,版本统一

直接依赖引入具体版本(maven的就近依赖原则)


<dependency>
    <groupId>mysqlgroupId>
    <artifactId>mysql-connector-javaartifactId>
    <version>8.0.26version>
dependency>
1.2 分析自动配置
  • DataSourceAutoConfiguration : 数据源的自动配置。

    • 修改数据源相关的配置:spring.datasource
    • 数据库连接池的配置:如果容器中没有数据源,就默认给你放一个。
    • 底层配置好的连接池是:HikariDataSource
  • DataSourceTransactionManagerAutoConfiguration: 事务管理器的自动配置

  • JdbcTemplateAutoConfigurationJdbcTemplate的自动配置,可以来对数据库进行CRUD

    • 可以修改前缀为spring.jdbc的配置项来修改JdbcTemplate
    • @Bean @Primary JdbcTemplate:Spring容器中有这个JdbcTemplate组件,使用@Autowired
  • JndiDataSourceAutoConfiguration: JNDI的自动配置

  • XADataSourceAutoConfiguration: 分布式事务相关的

1.3 修改配置项
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/fkddatabase
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
1.4 测试
@Slf4j
@SpringBootTest
class BootAdminApplicationTests {
    //因为容器中注入了JdbcTemplate组件,所以可以自动注入
    @Autowired
    JdbcTemplate jdbcTemplate;

    @Test
    void contextLoads() {
        Long aLong = jdbcTemplate.queryForObject("select count(*) from emp", Long.class);
        log.info("总记录数是:{}", aLong);
    }
}
2. 使用Druid数据源 2.1 druid官方github地址

Druid是数据库连接池,它能够提供强大的监控和扩展功能

Druid官方github地址

Spring Boot整合第三方技术的两种方式:

  • 自定义(自定义configuration类,参考配置文档@Bean组件)

  • 找starter场景

2.2 使用官方starter的方式

官方文档 - Druid Spring Boot Starter

  • 引入依赖:

    <dependency>
        <groupId>com.alibabagroupId>
        <artifactId>druid-spring-boot-starterartifactId>
        <version>1.1.17version>
    dependency>
    
  • 分析自动配置(DruidDataSourceAutoConfigure):

    • 扩展配置项 spring.datasource.druid
    • 自动配置类DruidDataSourceAutoConfigure
    • DruidSpringAopConfiguration.class, 监控SpringBean的;配置项:spring.datasource.druid.aop-patterns
    • DruidStatViewServletConfiguration.class, 监控页的配置。spring.datasource.druid.stat-view-servlet默认开启
    • DruidWebStatFilterConfiguration.class,web监控配置。spring.datasource.druid.web-stat-filter默认开启
    • DruidFilterConfiguration.class:所有Druid的filter的配置
    private static final String FILTER_STAT_PREFIX = "spring.datasource.druid.filter.stat";
    private static final String FILTER_CONFIG_PREFIX = "spring.datasource.druid.filter.config";
    private static final String FILTER_ENCODING_PREFIX = "spring.datasource.druid.filter.encoding";
    private static final String FILTER_SLF4J_PREFIX = "spring.datasource.druid.filter.slf4j";
    private static final String FILTER_LOG4J_PREFIX = "spring.datasource.druid.filter.log4j";
    private static final String FILTER_LOG4J2_PREFIX = "spring.datasource.druid.filter.log4j2";
    private static final String FILTER_COMMONS_LOG_PREFIX = "spring.datasource.druid.filter.commons-log";
    private static final String FILTER_WALL_PREFIX = "spring.datasource.druid.filter.wall";
    
  • 配置示例:

    • 具体配置项参照官方文档
    • DruidDataSource配置属性列表
    spring:
      datasource:
        url: jdbc:mysql://localhost:3306/fkddatabase
        username: root
        password: 123456
        driver-class-name: com.mysql.cj.jdbc.Driver
    
        druid:
          aop-patterns: com.zju.admin.*  #监控SpringBean
          filters: stat,wall     # 底层开启功能,stat(sql监控),wall(防火墙)
    
          stat-view-servlet:   # 配置监控页功能
            enabled: true
            login-username: admin
            login-password: 123456
            resetEnable: false
    
          web-stat-filter:  # 监控web
            enabled: true
            urlPattern: /*
            exclusions: '*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*'
    
    
          filter:
            stat:    # 对上面filters里面的stat的详细配置
              slow-sql-millis: 1000
              logSlowSql: true
              enabled: true
            wall:
              enabled: true
              config:
                drop-table-allow: false
    
  • 访问监控页首页

    http://localhost:8080/druid

3. 整合MyBatis *** 作

MyBatis的GitHub仓库

MyBatis官方

starter的命名方式:

  1. SpringBoot官方的Starter:spring-boot-starter-*
  2. 第三方的starter: *-spring-boot-starter
  • 引入依赖:
<dependency>
    <groupId>org.mybatis.spring.bootgroupId>
    <artifactId>mybatis-spring-boot-starterartifactId>
    <version>2.1.4version>
dependency>
3.1 配置模式
  • 全局配置文件MybatisAutoConfiguration,读取配置项绑定类
  • SqlSessionFactory:自动配置好了
  • SqlSession:自动配置了SqlSessionTemplate 组合了SqlSession,真正对数据库CRUD
  • @Import(AutoConfiguredMapperScannerRegistrar.class)
  • Mapper: 只要我们写的 *** 作MyBatis的接口标标注了@Mapper就会被自动扫描进来

实例 *** 作:

1. 配置文件application.yaml:

spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/fkddatabase
    driver-class-name: com.mysql.cj.jdbc.Driver

# 配置mybatis规则(代替mabatis-config.xml)
mybatis:
  mapper-locations: classpath:mapper/*.xml  #sql映射文件位置
  configuration:
    map-underscore-to-camel-case: true
  type-aliases-package: com.zju.admin

2. Springboot2不需要mybatis-config文件

3. 创建XXXmapper接口与对应XXXmapper.xml

  • 创建数据表对应的实体类
@ToString
@NoArgsConstructor
@Data
public class Emp {
    private String ename;
    private Double sal;
}
  • Mapper接口
@Mapper
public interface ResultMapper {
    /**
     * 根据姓名查询
     * @param name
     * @return
     */
    public Emp getEmp(@Param("name") String name);
}
  • sql映射文件

DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zju.admin.mapper.ResultMapper">

    
    <select id="getEmp" resultType="emp">
        select * from `result` where ename=#{name};
    select>
mapper>

4. Service和Controller层

@Service
public class ResultService {

    @Autowired
    ResultMapper resultMapper;

    public Emp getEmpByName(String name){
        return resultMapper.getEmp(name);
    }
}
@Controller
public class IndexController {
    
    @Autowired
    ResultService resultService;

    @ResponseBody
    @RequestMapping("/emp/{empName}")
    public Emp getByName(@PathVariable("empName") String name){
        Emp emp = resultService.getEmpByName(name);
        return emp;
    }
}

总结:

  • 导入mybatis官方starter
  • 编写mapper接口。标准@Mapper注解
  • 编写sql映射文件并绑定mapper接口
  • 在application.yaml中指定Mapper配置文件的位置,以及指定全局配置文件的信息
3.2 注解模式

1.可以通过Spring Initializr添加MyBatis的Starter

2. 省去XXXmapper.xml,在接口上加注解

@Select("select * from `result` where sal>#{sal}")
public List<Emp> getEmpBySal(@Param("sal") Double sal);
3.3 混合模式

实际开发中简单的CRUD可以写在注解上,复杂的业务用xml文件配置方式

  • ResultMapper
@Mapper
public interface ResultMapper {
    /**
     * 根据姓名查询
     * @param name
     * @return
     */
    public Emp getEmp(@Param("name") String name);

    /**
     * 根据收入查询
     * @param sal
     * @return
     */
    @Select("select * from `result` where sal>#{sal}")
    public List<Emp> getEmpBySal(@Param("sal") Double sal);

    /**
     * 插入员工,json显示自增主键
     * @param emp
     * @return
     */
    @Insert("insert into `result`(`ename`,`sal`) values(#{ename},#{sal}) ")
    @Options(useGeneratedKeys = true, keyProperty = "id")
    public void insertEmp(Emp emp);
}
  • ResultMapper.xml

DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zju.admin.mapper.ResultMapper">

    
    <select id="getEmp" resultType="emp">
        select * from `result` where ename=#{name}
    select>
    
mapper>
3.4 最佳实战
  • 引入mybatis-starter
  • 配置application.yaml中,指定mapper-location位置即可
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/fkddatabase
    username: root
    password: 123456
# 配置mybatis规则
mybatis:
  mapper-locations: classpath:mybatis/mapper/*.xml  #sql映射文件位置
  configuration:
    map-underscore-to-camel-case: true
  type-aliases-package: com.zju.admin
  • 编写Mapper接口并标注@Mapper注解

    • 简单方法直接注解方式

    • 复杂方法编写mapper.xml进行绑定映射

  • @MapperScan(“com.zju.admin.mapper”) 简化,其他的接口就可以不用标注@Mapper注解

@MapperScan("com.zju.admin.mapper")
@SpringBootApplication
public class MainApplication {

    public static void main(String[] args) {
        SpringApplication.run(MainApplication.class, args);
    }
}
4. 整合MyBatis-Plus完成CRUD

MyBatis-Plus(简称 MP)是一个 MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生

4.1 整合MyBatis-Plus

1. 引入依赖

<dependency>
    <groupId>com.baomidougroupId>
    <artifactId>mybatis-plus-boot-starterartifactId>
    <version>3.5.1version>
dependency>

什么都配置好了,注意默认规则:

  • MybatisPlusAutoConfiguration配置类,MybatisPlusProperties配置项绑定
    • mybatis-plus:xxx就是对mabtis-plus的定制
  • SqlSessionFactory自动配置好,底层是容器中默认的数据源。
  • mapperLocations自动配置好的,有默认值classpath*:/mapper/**/*.xml,这表示任意包的类路径下的所有mapper文件夹下任意路径下的所有xml都是sql映射文件。 建议以后sql映射文件放在 mapper下
  • 容器中也自动配置好了SqlSessionTemplate
  • @Mapper 标注的接口也会被自动扫描,建议直接 @MapperScan("com.zju.admin.mapper")批量扫描

2. 配置数据源

  • application.yml 配置文件中添加mysql 数据库的相关配置
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/fkddatabase
    username: root
    password: 123456
  • 在 Spring Boot 启动类中添加 @MapperScan 注解,扫描 Mapper 文件夹:
@MapperScan("com.zju.admin.mapper")
@SpringBootApplication
public class BootAdminApplication {

    public static void main(String[] args) {
        SpringApplication.run(BootAdminApplication.class, args);
    }
}
  • 编写对应POJO
    • Mybatis-plus通过数据库pojo名小写得到数据库表名,从而建立对应关系(User类——user表)
    • 可通过@TableName指定
@AllArgsConstructor
@NoArgsConstructor
@Data
@TableName("tb_user")
public class User {
    //两个临时属性,不对应表中的内容
    @TableField(exist = false)
    private String userName;
    @TableField(exist = false)
    private String password;

    private Long id;
    private String name;
    private Integer age;
    private String email;
}
  • 查询的字段名要与属性名对应
    • 通过查询起别名方式
    • 通过resultMap建立自定义映射关系

3. 编写业务接口

  • UserMapper
/**
 * 只需要我们的Mapper继承MyBatisPlus的BaseMapper就可以拥有CRUD能力,减轻开发工作
 */
public interface UserMapper extends BaseMapper<User> {
}

当复杂业务时考虑在resources/mapper下编写业务对应的sql映射xml文件

使用MyBatis Plus提供的IServiceServiceImpl,减轻Service层开发工作:

  • UserService
public interface UserService extends IService<User> {
}
  • UserServiceImpl
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService{
}
4.2 CRUD

1. 添加分页插件

@Configuration
public class MybatisPlusConfig {

    /**
     * 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除)
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
        return interceptor;
    }
}

2. 分页数据展示即删除用户

  • 控制层
@GetMapping("/dynamic_table")
public String dynamic_table(Model model, @RequestParam(value = "pn", defaultValue = "1") Long pn){

    //分页查询数据
    Page<User> userPage = new Page<>(pn, 2);

    //分页查询结果
    Page<User> page = userService.page(userPage, null);
    model.addAttribute("page",page);

    return "table/dynamic_table";
}

@GetMapping("/user/delete/{id}")
public String deleteUser(@PathVariable("id") Long id,
                         @RequestParam(value = "pn", defaultValue = "1") Long pn,
                         RedirectAttributes redirectAttributes){
    userService.removeById(id);
    //重定向携带参数
    redirectAttributes.addAttribute("pn", pn);
    return "redirect:/dynamic_table";
}
  • 页面渲染
<div class="adv-table">
    <table class="display table table-bordered" id="hidden-table-info">
        <thead>
            <tr>
                <th>序号th>
                <th>idth>
                <th>nameth>
                <th>ageth>
                <th>emailth>
                <th> *** 作th>
            tr>
        thead>
        <tbody>
            <tr class="gradeX" th:each="user,status: ${page.records}">
                <td th:text="${status.count}">td>
                <td th:text="${user.id}">td>
                <td>[[${user.name}]]td>
                <td>[[${user.age}]]td>
                <td>[[${user.email}]]td>
                <td><a th:href="@{/user/delete/{id}(id=${user.id},pn=${page.current})}" class="btn btn-danger" type="button">删除a>td>
            tr>
        tbody>
    table>

    <div class="row-fluid">
        <div class="span6">
            <div class="dataTables_info" id="dynamic-table_info">当前 [[${page.current}]] 页
                总计 [[${page.pages}]] 页 共 [[${page.total}]] 条记录
            div>
        div>
        <div class="span6">
            <div class="dataTables_paginate paging_bootstrap pagination">
                <ul>
                    <li class="prev disabled"><a href="#">← Previousa>li>
                    <li th:class="${num == page.current?'active':''}" th:each="num:${#numbers.sequence(1,page.pages)}">
                        <a th:href="@{/dynamic_table(pn=${num})}">[[${num}]]a>
                    li>

                    <li class="next"><a href="#">Next → a>li>
                ul>
            div>
        div>
    div>
div>
二、NoSQL 1. Redis自动配置

添加依赖:

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-data-redisartifactId>
dependency>


<dependency>
    <groupId>redis.clientsgroupId>
    <artifactId>jedisartifactId>
dependency>
  • spring-boot-autoconfigure—data—redis—RedisAutoConfiguration自动配置类,RedisProperties 属性类 --> spring.redis.xxx是对redis的配置
  • 连接工厂LettuceConnectionConfigurationJedisConnectionConfiguration是准备好的。
  • 自动注入了RedisTemplatexxxTemplate
  • 自动注入了StringRedisTemplate,key,value都是String
  • 底层只要我们使用StringRedisTemplateRedisTemplate就可以 *** 作Redis。

外网Redis环境搭建:

  1. 阿里云按量付费Redis,其中选择经典网络。

  2. 申请Redis的公网连接地址。

  3. 修改白名单,允许0.0.0.0/0访问。

  • Redis Desktop Manager:可视化Redis管理软件
2. RedisTemplate与Lettuce

测试redis连接:

@SpringBootTest
public class Boot05WebAdminApplicationTests {

    @Autowired
    StringRedisTemplate redisTemplate;

    @Autowired
    RedisConnectionFactory redisConnectionFactory;

    @Test
    void testRedis(){
        ValueOperations<String, String> operations = redisTemplate.opsForValue();
        operations.set("hello","world");

        String hello = operations.get("hello");
        System.out.println(hello);

        System.out.println(redisConnectionFactory.getClass());
    }
}
3. 切换至jedis
spring:
  redis:
#   url: redis://lfy:Lfy123456@r-bp1nc7reqesxisgxpipd.redis.rds.aliyuncs.com:6379
    host: r-bp1nc7reqesxisgxpipd.redis.rds.aliyuncs.com
    port: 6379
    password: lfy:Lfy123456
    client-type: jedis
    jedis:
      pool:
        max-active: 10
#   lettuce:# 另一个用来连接redis的java框架
#      pool:
#        max-active: 10
#        min-idle: 5

Redis *** 作与统计小实验:

  • URL统计拦截器
@Component
public class RedisUrlCountInterceptor implements HandlerInterceptor {

    @Autowired
    StringRedisTemplate redisTemplate;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String uri = request.getRequestURI();
        //默认每次访问当前uri就会计数+1
        redisTemplate.opsForValue().increment(uri);
        return true;
    }
}
  • 注册URL统计拦截器:
@Configuration
public class AdminWebConfig implements WebMvcConfigurer{

    @Autowired
    RedisUrlCountInterceptor redisUrlCountInterceptor;

	@Override
    public void addInterceptors(InterceptorRegistry registry) {
        //将拦截器注册到容器中.拦截所有请求.放行的请求
        registry.addInterceptor(new LoginInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns("/","/login","/css/**","/fonts/**","/images/**","/js/**");
        registry.addInterceptor(redisUrlCountInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/","/login","/css/**","/fonts/**","/images/**",
                        "/js/**","/aa/**");
    }
}

Filter、Interceptor 几乎拥有相同的功能,都是拦截作用?

  • Filter是Servlet定义的原生组件,它的好处是脱离Spring应用也能使用。
  • Interceptor是Spring定义的接口,可以使用Spring的自动装配等功能。

调用Redis内的统计数据:

@Slf4j
@Controller
public class IndexController {

	@Autowired
    StringRedisTemplate redisTemplate;
    
	@GetMapping("/main.html")
    public String mainPage(HttpSession session,Model model){

        log.info("当前方法是:{}","mainPage");

        ValueOperations<String, String> opsForValue =
                redisTemplate.opsForValue();

        String s = opsForValue.get("/main.html");
        String s1 = opsForValue.get("/sql");

        model.addAttribute("mainCount",s);
        model.addAttribute("sqlCount",s1);

        return "main";
    }
}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/794622.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-06
下一篇 2022-05-06

发表评论

登录后才能评论

评论列表(0条)

保存