【SpringBoot2入门】002.集成数据层框架

《SpringBoot+SpringCloud+Vue+Element项目实战:手把手教你开发权限管理系统》读书笔记

集成持久层框架

在 java 应用的数据库开发中,不可避免地会使用到持久层框架,而现在开源项目中持久层框架用到最多的基本就是 iBatis、myBatis 和 Hibernate 了。

集成MyBatis框架

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

  • 官方文档:https://mybatis.org/mybatis-3/
  • 中文官网:http://www.mybatis.cn/
  • 参考教程:https://www.w3cschool.cn/mybatis/
1、添加依赖

Spring Boot 对于MyBaits的支持需要引入mybatis-spring-boot-starter的依赖。

<!--MyBatis支持-->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.3.2</version>
</dependency>
<!--mysql支持-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
2、配置类
  1. 添加MyBatis配置类MybatisConfig.java:
    Mybatis配置类
  2. 在application.yml中添加数据源配置:
    spring:
      datasource:
        driverClassName: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
        username: root
        password: 123456
    
  3. 配置包扫描
    给启动类的注解@SpringBootApplication配置包扫描,明确启动时自动扫描哪个包。(Spring Boot默认会扫描启动类包及子包的组件,所以此处也可以不配置)
@SpringBootApplication(scanBasePackages={"com.example.demo"})
3、生成模块

MyBatis官方也提供了生成工具(MyBaits Generator)来快速的生成MyBatis的Model、DAO、XML映射文件,另外阿里的MyBatis Plus实现此功能也很优秀。

  • Mybatis Generator官网:http://www.mybatis.org/generator/index.html
  • Mybatis Generator教程:https://blog.csdn.net/testcs_dn/article/details/77881776
  • MyBatis Plus官网:http://mp.baomidou.com/#/
4、编写服务接口
  1. 在Mapper文件SysUserMapper.java中新添加一个findAll方法,用于查询所有的用户信息。
  2. 在映射文件SysUserMapper.xml中添加一个查询方法,编写findAll的查询语句。
  3. 在接口类SysUserService.java中编写用户管理接口,包含一个findAll方法。
  4. 在实现类SysUserServiceImpl.java中编写用户管理实现类,调用SysUserMapper方法完成查询操作。
  5. 在控制类SysUserController.Java中编写用户管理RESTful接口,返回JSON数据格式,提供外部调用。被@RestController注解的接口控制器默认使用JSON格式交互,返回JSON结果。
5、配置打包资源

XML映射文件是不在默认打包范围内的,所以需要修改一下打包资源配置。修改pom.xml,在build标签内加入形式如下的resource标签的打包配置,这样打包时就会把MyBatis映射文件也复制过去了。

6、编译运行

编译并启动应用,访问http://127.0.0.1:1111/user/findAll,可以看到查询接口成功返回了所有用户信息。

集成Spring Data JPA

1、添加依赖

Spring Boot 对于MyBaits的支持需要引入spring-boot-starter-data-jpa的依赖。

<!--Spring Data JPA支持-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
2、修改配置

修改application.yml中的数据源和JPA配置:

spring:
  datasource:
	driverClassName: com.mysql.cj.jdbc.Driver
	url: jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
	username: root
	password: 123456
  jpa:
    database: MySQL
    database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
    show-sql: true
    hibernate:
      ddl-auto: update
3、生成实体类

使用IDEA的插件生成实体类。

  1. 在项目结构Project Structure中添加JPA模块,点击确定。
    添加JPA模块
    2.使用Persistence工具生成带注解的实体类:打开Persistence工具栏, 右键项目: Generate Persistence Mapping - By Database Schema
    Persistence工具
    Persistence工具
4、启动测试

在启动服务时,若提示Could not create connection to database server. Attempted reconnect 3 times. Giving up.错误,可用如下方法解决。

解决方案1:这是由于数据库和系统时区差异所造成的,在数据库连接字符串后面加上serverTimezone=UTC,其中UTC是统一标准世界时间。
解决方案2:使用低版本的MySQL jdbc驱动,5.1.30版本不会存在时区的问题。

集成Druid数据源

Spring Boot默认提供了若干种可用的连接池,默认的数据源是org.apache.tomcat.jdbc.pool.DataSource。Druid是阿里系提供的一个开源连接池,除在连接池之外,还提供了非常优秀的数据库监控和扩展功能。更多详细信息可参考官方文档,https://github.com/alibaba/druid/wiki。

1、添加依赖

Druid Spring Boot Starter是阿里官方提供的Spring Boot插件,用于帮助在Spring Boot项目中轻松集成Druid数据库连接池和监控。

<!--Druid数据源支持-->
<dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>druid-spring-boot-starter</artifactId>
   <version>1.1.10</version>
</dependency>
2、修改配置

把原有的数据源配置替换成 druid 数据源并配置数据源相关参数。

# DataSource
spring:
  datasource:
    name: druidDataSource
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC
      username: root
      password: 123456
      filters: stat,wall,log4j,config
      max-active: 100
      initial-size: 1
      max-wait: 60000
      min-idle: 1
      time-between-eviction-runs-millis: 60000
      min-evictable-idle-time-millis: 300000
      validation-query: select 'x'
      test-while-idle: true
      test-on-borrow: false
      test-on-return: false
      pool-prepared-statements: true
      max-open-prepared-statements: 50
      max-pool-prepared-statement-per-connection-size: 20

参数说明:

  • spring.datasource.druid.max-active 最大连接数
  • spring.datasource.druid.initial-size 初始化大小
  • spring.datasource.druid.min-idle 最小连接数
  • spring.datasource.druid.max-wait 获取连接等待超时时间
  • spring.datasource.druid.time-between-eviction-runs-millis 间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
  • spring.datasource.druid.min-evictable-idle-time-millis 一个连接在池中最小生存的时间,单位是毫秒
  • spring.datasource.druid.filters=config,stat,wall,log4j 配置监控统计拦截的filters,去掉后监控界面SQL无法进行统计,’wall’用于防火墙

如果需要通过定制的配置文件对Druid进行自定义属性配置,添加配置类DruidDataSourceProperties.java如下:

package com.example.demo.config;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "spring.datasource.druid")
public class DruidDataSourceProperties {

    // jdbc
    private String driverClassName;
    private String url;
    private String username;
    private String password;
    // jdbc connection pool
    private int initialSize;
    private int minIdle;
    private int maxActive = 100;
    private long maxWait;
    private long timeBetweenEvictionRunsMillis;
    private long minEvictableIdleTimeMillis;
    private String validationQuery;
    private boolean testWhileIdle;
    private boolean testOnBorrow;
    private boolean testOnReturn;
    private boolean poolPreparedStatements;
    private int maxPoolPreparedStatementPerConnectionSize;
    // filter
    private String filters;

    public int getInitialSize() {
        return initialSize;
    }

    public void setInitialSize(int initialSize) {
        this.initialSize = initialSize;
    }

    public int getMinIdle() {
        return minIdle;
    }

    public void setMinIdle(int minIdle) {
        this.minIdle = minIdle;
    }

    public int getMaxActive() {
        return maxActive;
    }

    public void setMaxActive(int maxActive) {
        this.maxActive = maxActive;
    }

    public long getMaxWait() {
        return maxWait;
    }

    public void setMaxWait(long maxWait) {
        this.maxWait = maxWait;
    }

    public long getTimeBetweenEvictionRunsMillis() {
        return timeBetweenEvictionRunsMillis;
    }

    public void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) {
        this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
    }

    public long getMinEvictableIdleTimeMillis() {
        return minEvictableIdleTimeMillis;
    }

    public void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) {
        this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
    }

    public String getValidationQuery() {
        return validationQuery;
    }

    public void setValidationQuery(String validationQuery) {
        this.validationQuery = validationQuery;
    }

    public boolean isTestWhileIdle() {
        return testWhileIdle;
    }

    public void setTestWhileIdle(boolean testWhileIdle) {
        this.testWhileIdle = testWhileIdle;
    }

    public boolean isTestOnBorrow() {
        return testOnBorrow;
    }

    public void setTestOnBorrow(boolean testOnBorrow) {
        this.testOnBorrow = testOnBorrow;
    }

    public boolean isTestOnReturn() {
        return testOnReturn;
    }

    public void setTestOnReturn(boolean testOnReturn) {
        this.testOnReturn = testOnReturn;
    }

    public boolean isPoolPreparedStatements() {
        return poolPreparedStatements;
    }

    public void setPoolPreparedStatements(boolean poolPreparedStatements) {
        this.poolPreparedStatements = poolPreparedStatements;
    }

    public int getMaxPoolPreparedStatementPerConnectionSize() {
        return maxPoolPreparedStatementPerConnectionSize;
    }

    public void setMaxPoolPreparedStatementPerConnectionSize(int maxPoolPreparedStatementPerConnectionSize) {
        this.maxPoolPreparedStatementPerConnectionSize = maxPoolPreparedStatementPerConnectionSize;
    }

    public String getFilters() {
        return filters;
    }

    public void setFilters(String filters) {
        this.filters = filters;
    }

    public String getDriverClassName() {
        return driverClassName;
    }

    public void setDriverClassName(String driverClassName) {
        this.driverClassName = driverClassName;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

}

问题:配置之后,文件上方有红色提示如下
Druid配置文件问题
解决方法:点击后面的 Open Documentation… 会弹出相关网站,里面有解决办法,很简单,导入对应的依赖就可以:
Druid配置文件问题解决方法

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-configuration-processor</artifactId>
	<optional>true</optional>
</dependency>

Druid Spring Starter 简化了很多配置,如果默认配置满足不了你的需求,可以自定义配置。更多配置参考: https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter

3、配置Servlet和Filter

在config包下新建一个DruidConfig配置类,主要是注入属性和配置连接池相关的配置,如黑白名单、监控管理后台登录账户密码等,DruidConfig.java内容如下:

package com.example.demo.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import javax.servlet.Servlet;
import javax.sql.DataSource;
import java.sql.SQLException;

@Configuration
@EnableConfigurationProperties({DruidDataSourceProperties.class})
public class DruidConfig {
    @Autowired
    private DruidDataSourceProperties properties;

    @Bean
    @ConditionalOnMissingBean
    public DataSource druidDataSource() {
        DruidDataSource druidDataSource = new DruidDataSource();
        druidDataSource.setDriverClassName(properties.getDriverClassName());
        druidDataSource.setUrl(properties.getUrl());
        druidDataSource.setUsername(properties.getUsername());
        druidDataSource.setPassword(properties.getPassword());
        druidDataSource.setInitialSize(properties.getInitialSize());
        druidDataSource.setMinIdle(properties.getMinIdle());
        druidDataSource.setMaxActive(properties.getMaxActive());
        druidDataSource.setMaxWait(properties.getMaxWait());
        druidDataSource.setTimeBetweenEvictionRunsMillis(properties.getTimeBetweenEvictionRunsMillis());
        druidDataSource.setMinEvictableIdleTimeMillis(properties.getMinEvictableIdleTimeMillis());
        druidDataSource.setValidationQuery(properties.getValidationQuery());
        druidDataSource.setTestWhileIdle(properties.isTestWhileIdle());
        druidDataSource.setTestOnBorrow(properties.isTestOnBorrow());
        druidDataSource.setTestOnReturn(properties.isTestOnReturn());
        druidDataSource.setPoolPreparedStatements(properties.isPoolPreparedStatements());
        druidDataSource.setMaxPoolPreparedStatementPerConnectionSize(properties.getMaxPoolPreparedStatementPerConnectionSize());

        try {
            druidDataSource.setFilters(properties.getFilters());
            druidDataSource.init();
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return druidDataSource;
    }

    /**
     * 注册Servlet信息, 配置监控视图
     *
     * @return
     */
    @Bean
    @ConditionalOnMissingBean
    public ServletRegistrationBean<Servlet> druidServlet() {
        ServletRegistrationBean<Servlet> servletRegistrationBean = new ServletRegistrationBean<Servlet>(new StatViewServlet(), "/druid/*");

        //白名单:
        servletRegistrationBean.addInitParameter("allow","");
        //IP黑名单 (存在共同时,deny优先于allow) : 如果满足deny的话提示:Sorry, you are not permitted to view this page.
        servletRegistrationBean.addInitParameter("deny","");
        //登录查看信息的账号密码, 用于登录Druid监控后台
        servletRegistrationBean.addInitParameter("loginUsername", "admin");
        servletRegistrationBean.addInitParameter("loginPassword", "admin");
        //是否能够重置数据.
        servletRegistrationBean.addInitParameter("resetEnable", "true");
        return servletRegistrationBean;

    }

    /**
     * 注册Filter信息, 监控拦截器
     *
     * @return
     */
    @Bean
    @ConditionalOnMissingBean
    public FilterRegistrationBean<Filter> filterRegistrationBean() {
        FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<Filter>();
        filterRegistrationBean.setFilter(new WebStatFilter());
        filterRegistrationBean.addUrlPatterns("/*");
        filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
        return filterRegistrationBean;
    }
}
  • @EnableConfigurationProperties注解用于导入上一步Druid的配置信息。
  • public ServletRegistrationBean druidServlet()相当于Web Servlet配置。
  • public FilterRegistrationBean filterRegistrationBean()相当于Web Filter配置。
4、启动测试

问题:编译启动时,报错Factory method 'druidDataSource' threw exception; nested exception is java.lang.NoClassDefFoundError: org/apache/log4j/Logger

解决方法:由于监控功能会用到log4j,所以log4j需一并引入。首先引入log4j依赖:

<!-- log4j -->
<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
</dependency>

然后进行log4j的配置,增加配置文件log4j.properties,放在resource目录下:

### set log levels ###
log4j.rootLogger = INFO, console, infoFile, errorFile 
LocationInfo = true    

log4j.appender.console = org.apache.log4j.ConsoleAppender  
log4j.appender.console.Target = System.out  
log4j.appender.console.layout = org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern = [%d{yyyy-MM-dd HH:mm:ss,SSS}]-[%p]:%m   %x %n 

log4j.appender.infoFile = org.apache.log4j.DailyRollingFileAppender  
log4j.appender.infoFile.Threshold = INFO  
log4j.appender.infoFile.File = D:/logs/log
log4j.appender.infoFile.DatePattern = '.'yyyy-MM-dd'.log'  
log4j.appender.infoFile.Append = true
log4j.appender.infoFile.layout = org.apache.log4j.PatternLayout  
log4j.appender.infoFile.layout.ConversionPattern = [%d{yyyy-MM-dd HH:mm:ss,SSS}]-[%p]:%m  %x %n 

log4j.appender.errorFile = org.apache.log4j.DailyRollingFileAppender  
log4j.appender.errorFile.Threshold = ERROR  
log4j.appender.errorFile.File = D:/logs/error  
log4j.appender.errorFile.DatePattern = '.'yyyy-MM-dd'.log'  
log4j.appender.errorFile.Append = true  
log4j.appender.errorFile.layout = org.apache.log4j.PatternLayout  
log4j.appender.errorFile.layout.ConversionPattern = [%d{yyyy-MM-dd HH:mm:ss,SSS}]-[%p]:%m  %x %n
5、查看监控

启动应用,访问: http://127.0.0.1:1111/druid/login.html, 进入Druid监控后台页面。
登录连接池监控

问题:访问监控地址,报错Sorry, you are not permitted to view this page.

解决方法:连接池servlet配置中,添加白名单allow配置servletRegistrationBean.addInitParameter("allow","");,若要设置多个ip可以访问连接池监控,需要用逗号分开。
解决方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值