封面画师:adsuger     封面ID:76752964

1. 整合JDBC

1.1 SpringData

  • 对于数据访问层,无论是 SQL(关系型数据库) 还是 NOSQL(非关系型数据库),Spring Boot 底层都是采用 Spring Data 的方式进行统一处理。

  • Spring Boot 底层都是采用 Spring Data 的方式进行统一处理各种数据库,Spring Data 也是 Spring 中与 Spring Boot、Spring Cloud 等齐名的知名项目。

  • Sping Data 官网:点击查看

1.2 整合JDBC

  1. 创建SpringBoot项目,并导入对应的模块:

JDBC依赖导入

  1. 项目建好后,会自动导入相关的启动器;
  2. 编写yaml配置文件链接数据库:
1
2
3
4
5
6
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql:///sboot?serverTimezone=GMT%2b8&useUnicode=true&characterEncoding=utf-8&useSSL=false
driver-class-name: com.mysql.cj.jdbc.Driver
  1. 到此,我们就已经完成了基本配置,其他的配置SpringBoot会帮我们自动配置。

1.3 数据源

  • 我们连接好数据库后,可以进行测试。测试后发现,我们可以发现SpringBoot默认给我们配置的数据源是class com.zaxxer.hikari.HikariDataSource。

  • 我们可以进行全局搜索,找到数据源的所有配置都在DataSourceAutoConfiguration文件。这里导入的类都在 DataSourceConfiguration 配置类下,可以看出 Spring Boot 2.2.4 默认使用HikariDataSource 数据源。

  • 小道消息:HikariDataSource 号称 Java WEB 当前速度最快的数据源,相比于传统的 C3P0 、DBCP、Tomcat jdbc 等连接池更加优秀;

  • 自定义数据源类型:使用 spring.datasource.type 指定自定义的数据源类型,值为 要使用的连接池实现的完全限定名。

1.4 JDBCTemplate

  1. 有了数据源,我们就可以拿到数据库连接,然后使用原生的 JDBC 语句来操作数据库。

  2. 即使不使用第三方第数据库操作框架,如 MyBatis等,Spring 本身也对原生的JDBC 做了轻量级的封装,即JdbcTemplate。数据库操作的所有 CRUD 方法都在 JdbcTemplate 中。xxxxTemplate相当于SpringBoot给我们配置好的模板bean,拿来即用。

  3. 当然,Spring Boot 默认已经配置好了 JdbcTemplate ,程序员只需注入就可以使用。

  4. JdbcTemplate 的自动配置是依赖 org.springframework.boot.autoconfigure.jdbc 包下的 JdbcTemplateConfiguration 类。


JdbcTemplate主要提供以下几类方法:

  • execute方法:可以用于执行任何SQL语句,一般用于执行DDL语句;
  • update方法及batchUpdate方法:update方法用于执行新增、修改、删除等语句;batchUpdate方法用于执行批处理相关语句;
  • query方法及queryForxxx方法:用于执行查询相关语句;
  • call方法:用于执行存储过程、函数相关语句。

代码测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
@RestController
public class JDBCController {

@Autowired
JdbcTemplate jdbcTemplate;

//查询数据库的所有信息
@GetMapping("/userList")
public List<Map<String, Object>> userList() {
String sql = "select * from account";
List<Map<String, Object>> list_maps = jdbcTemplate.queryForList(sql);
return list_maps;
}

@GetMapping("/addUser")
public String addUser() {
String sql = "insert into account(name,money,password) values ('小明',12,'15987')";
jdbcTemplate.update(sql);
return "update-ok";
}

@GetMapping("/updateUser/{id}")
public String updateUser(@PathVariable("id") int id) {
String sql = "update account set name=?,money=? where id=" + id;

//封装
Object[] objects = new Object[2];
objects[0] = "eeee";
objects[1] = 98;
jdbcTemplate.update(sql, objects);
return "update-ok";
}

@GetMapping("/deleteUser/{id}")
public String deleteUser(@PathVariable("id") int id) {
String sql = "delete from account where id = ?";
jdbcTemplate.update(sql, id);
return "delete-ok!";
}
}

2. 整合Druid

2.1 Druid简介

Java程序很大一部分要操作数据库,为了提高性能操作数据库的时候,又不得不使用数据库连接池。

Druid 是阿里巴巴开源平台上一个数据库连接池实现,结合了 C3P0、DBCP 等 DB 池的优点,同时加入了日志监控。

Druid 可以很好的监控 DB 池连接和 SQL 的执行情况,天生就是针对监控而生的 DB 连接池。

Druid已经在阿里巴巴部署了超过600个应用,经过一年多生产环境大规模部署的严苛考验。

Spring Boot 2.0 以上默认使用 Hikari 数据源,可以说 Hikari 与 Driud 都是当前 Java Web 上最优秀的数据源,本节来重点介绍 Spring Boot 如何集成 Druid 数据源,如何实现数据库监控。

Github地址:Druid

com.alibaba.druid.pool.DruidDataSource 基本配置参数如下:

Druid配置参数

2.2 添加数据源至项目

  • 添加Druid数据源依赖:

    1
    2
    3
    4
    5
    6
    <!-- druid -->
    <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.21</version>
    </dependency>
  • 由于SpringBoot默认数据源为Hikari,因此我们需要将其切换成Druid:

    1
    2
    3
    4
    5
    6
    7
    8
    spring:
    datasource:
    username: root
    password: 123456
    url: jdbc:mysql:///ssm?serverTimezone=GMT%2b8&useUnicode=true&characterEncoding=utf-8&useSSL=false
    driver-class-name: com.mysql.cj.jdbc.Driver
    # 切换数据源
    type: com.alibaba.druid.pool.DruidDataSource
  • 编写测试类,启动项目,检查数据源是否切换成功:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    @SpringBootTest
    class Springboot03DataApplicationTests {
    @Autowired
    DataSource dataSource;
    @Test
    void contextLoads() throws SQLException {
    //查看默认数据源 com.zaxxer.hikari.HikariDataSource
    System.out.println(dataSource.getClass());

    //获得数据库连接
    Connection connection = dataSource.getConnection();
    System.out.println(connection);
    //close
    connection.close();
    }
    }

    控制台显示:

    1
    2
    3
    class com.alibaba.druid.pool.DruidDataSource
    com.alibaba.druid.pool.DruidDataSource : {dataSource-1} inited
    com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@1f53481b

    表示切换成功!😎

  • 在配置文件中设置Druid的一些参数:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    spring:
    datasource:
    username: root
    password: 123456
    url: jdbc:mysql:///ssm?serverTimezone=GMT%2b8&useUnicode=true&characterEncoding=utf-8&useSSL=false
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource

    #Spring Boot 默认是不注入这些属性值的,需要自己绑定
    #druid 数据源专有配置
    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

    #配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入
    #如果允许时报错 java.lang.ClassNotFoundException: org.apache.log4j.Priority
    #则导入 log4j 依赖即可,Maven 地址: https://mvnrepository.com/artifact/log4j/log4j
    filters: stat,wall,log4j
    maxPoolPreparedStatementPerConnectionSize: 20
    useGlobalDataSourceStat: true
    connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
  • 由于我们在参数设置中添加了log4j,因此我们需要导入其依赖:

    1
    2
    3
    4
    5
    6
    <!--log4j-->
    <dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.17</version>
    </dependency>
  • 我们设置的参数暂时不会生效,没有对应的Starter来绑定这些参数,因此需要我们自己为DruidDataSource 绑定全局配置文件中的参数,再添加到容器中。编写一个配置类即可:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    @Configuration
    public class DruidConfig {

    /*
    将自定义的 Druid数据源添加到容器中
    将全局配置文件中前缀为 spring.datasource的属性值注入到 com.alibaba.druid.pool.DruidDataSource 的同名参数中
    */
    @ConfigurationProperties(prefix = "spring.datasource")
    @Bean
    public DataSource druidDataSource() {
    return new DruidDataSource();
    }
    }

2.3 数据监控

我们配置好Druid数据源后,发现与默认的数据源并没有什么区别,难道Druid仅此而已?

Druid的最重要特性就是可以进行数据监控,并且提供了一个Web界面方便用户查看,我们需要在配置类中设置以进行数据监控:

DruidConfig.java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//后台监控
// SpringBoot内置Servlet容器,没有web.xml,替代方法:druidDataSource,相当于web.xml
@Bean
public ServletRegistrationBean statViewServlet() {
ServletRegistrationBean<StatViewServlet> bean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*");

//后台登录密码配置
HashMap<String, String> initParameters = new HashMap<>();
//配置 put()第一个参数固定
initParameters.put("loginUsername", "admin"); //登录key都是固定的
initParameters.put("loginPassword", "123456");

//后台访问权限 参数为空,谁都能访问
initParameters.put("allow", "");
//initParams.put("allow", "localhost"):表示只有本机可以访问
//访问禁止人员 initParameters.put("用户名","IP地址");

bean.setInitParameters(initParameters);
return bean;
}

编写好代码后,我们可以启动项目,访问:http://localhost:8080/druid/login.html

Druid-index.html

然后我们输入在配置类中编写的登录用户名和密码进入后台监控页面:

Druid后台监控

我们可以上方导航栏切换不同的功能。

我们进行的所有操作都会被Druid进行监控,但是有一些请求我们不想被监控,我们可以在配置类中设置一个Druid监控过滤器:

DruidConfig.java:

1
2
3
4
5
6
7
8
9
10
11
12
13
//filter
@Bean
public FilterRegistrationBean webStatFilter() {
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new WebStatFilter());
//过滤请求
Map<String, String> initParameters = new HashMap<>();
//不进行监视统计的文件
initParameters.put("exclusions", "*.js,*.css,/druid/*");
bean.setInitParameters(initParameters);
// "/*" 表示过滤所有请求, 例如:bean.setUrlPatterns(Arrays.asList("/*"));
return bean;
}

3. 整合MyBatis

在Maven仓库中选择MyBatis需要的依赖:

1
2
3
4
5
6
7
8
9
10
11
<!-- mybatis-spring-boot-starter 整合-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>

从带入的依赖我们可以看出,MyBatis的Starter名为xxx-spring-boot-starter,表示这并不是SpringBoot官方的Starter,是第三方的Starter。

为了便于开发,我们一并导入了lombok, 记得在IDEA中添加lombok插件,否则代码无法运行

在配置文件在配置数据库连接信息:

1
2
3
4
5
6
7
8
9
10
11
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql:///ssm?serverTimezone=GMT%2b8&useUnicode=true&characterEncoding=utf-8&useSSL=false
driver-class-name: com.mysql.cj.jdbc.Driver

#整合Mybatis
mybatis:
type-aliases-package: com.yang.pojo
mapper-locations: classpath:mybatis/mapper/*.xml

编写pojo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Account {
private int id;
private String name;
private String password;
private float money;

public Account(String name, String password, float money) {
this.name = name;
this.password = password;
this.money = money;
}
}

编写mapper(CRUD全套搞起💪):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//表明这是一个mybatis的mapper类:Dao
// 除了这种方式,我们还可以在主启动类上添加注解@MapperScan(...)。
@Mapper
@Repository
public interface AccountMapper {

List<Account> queryAccountList();

Account queryAccountById(int id);

int addAccount(Account account);

int updateAccount(Account account);

int deleteAccount(int id);

}

小知识:接口中的变量int age = 18;默认表示为public static final int age = 18,即: 接口中的变量表示常量!

maven配置资源过滤问题

1
2
3
4
5
6
7
8
9
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>

编写到这,我们应该编写MyBatis的映射文件。在以前,我们会在mapper下创建映射文件,现在,建议 在resources目录下创建映射文件,但是这样我们就无法同时使用注解与配置文件

在resources目录下创建目录:mybatis/mapper,然后创建映射文件:AccountMapper.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yang.mapper.AccountMapper">

<!-- 我们在配置文件中设置了别名,所以对于pojo不用使用全类名 -->
<select id="queryAccountList" resultType="Account">
select * from account
</select>

<select id="queryAccountById" resultType="Account">
select * from account where id = #{id}
</select>

<insert id="addAccount" parameterType="Account">
insert into account (name,money,password) values (#{name},#{money},#{password})
</insert>

<update id="updateAccount" parameterType="Account">
update account set name = #{name},money=#{money} where id = #{id}
</update>

<delete id="deleteAccount" parameterType="int">
delete from account where id =#{id};
</delete>

</mapper>

编写Controller准备测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
@RestController
public class AccountController {

@Autowired
private AccountMapper accountMapper;

@GetMapping("/queryAccountList")
public List<Account> queryAccountList(){
List<Account> accounts = accountMapper.queryAccountList();
for (Account account:accounts){
System.out.println(account);
}
return accounts;
}

@GetMapping("/queryAccountById/{id}")
public Account queryAccountById(@PathVariable("id") int id){
Account account = accountMapper.queryAccountById(id);
System.out.println(account);
return account;
}

@GetMapping("/addAccount")
public String addAccount(){
accountMapper.addAccount(new Account("小安","123456",1000));
return "addAccount-ok";
}

@GetMapping("/updateAccount")
public String updateAccount(){
Account account = new Account();
account.setId(14);
account.setName("小暗");
account.setMoney(999);
accountMapper.updateAccount(account);
return "updateAccount-ok";
}

@GetMapping("/deleteAccount/{id}")
public String deleteAccount(@PathVariable("id") int id){
accountMapper.deleteAccount(id);
return "deleteAccount-ok";
}
}

数据库字段与实体类属性名不一致

由于大多数数据库设置不区分大小写 ,因此常采用下划线命名,比如:phone_code。而在 Java 中, 一般使用驼峰式命名,如:phoneCode。

MyBatis 还提供 了 一个全局属性 mapUnderscoreToCamelCase,通过配置这个属性为 true 可以自动将以下画线方式命名的数据库列映射到 Java 实体类的驼峰式命名属性中。这个属性 默认false ,如果想要使用该功能,需要在 MyBatis 的配置文件 中增加如下配置:

1
2
3
<settings>
<setting name="mapUnderscoreToCamelCase" value="true" />
</settings>

由于这里是 SpringBoot 项目,因此需要在配置文件 application.yaml 添加这样的配置:

1
2
3
mybatis:
configuration:
map-underscore-to-camel-case: true