动力节点王鹤SpringBoot3学习笔记——第四章 访问数据库

 

目录

第四章 访问数据库

 4.1 DataSource 

4.2 轻量的JdbcTemplate 

4.2.1 准备环境 

4.2.1.1  准备数据库和表脚本

4.2.1.2  创建Spring Boot工程

4.2.2 JdbcTemplate访问MySQL 

4.2.3 NamedParameterJdbcTemplate

4.2.4 多表查询

4.3 MyBatis 

4.3.1 单表CRUD 

4.3.2 ResultMap

4.3.3 SQL提供者 

4.3.4 @One一对一查询

4.3.5 @Many一对多查询

4.3.6 常用配置参数

4.3.7 MybatisAutoConfiguration

4.4 适合的连接池 

4.5 声明式事务

4.5.1.1 准备事务演示环境 

4.5.1.2 添加事务注解 

4.5.1.3 无效事务1 

4.5.1.4 无效事务2 

4.5.1.5 事务回滚规则

 


视频:动力节点SpringBoot3从入门到项目实战

第四章 访问数据库

Spring Boot框架为SQL数据库提供了广泛的支持,既有用JdbcTemplate直接访问JDBC,同时支持“object relational mapping”技术(如Hibernate,MyBatis)。Spring Data独立的项目提供对多种关系型和非关系型数据库的访问支持。比如 MySQL, Oracle , MongoDB , Redis, R2DBC,Apache Solr,Elasticsearch...

Spring Boot也支持嵌入式数据库比如H2, HSQL, and Derby。这些数据库只需要提供jar包就能在内存中维护数据。我们这章访问关系型数据库。 

 4.1 DataSource 

 通常项目中使用MySQL,Oracle,PostgreSQL等大型关系数据库。Java中的jdbc技术支持了多种关系型数据库的访问。在代码中访问数据库,我们需要知道数据库程序所在的ip,端口,访问数据库的用户名和密码以及数据库的类型信息。以上信息用来初始化数据源,数据源也就是DataSource。数据源表示数据的来源,从某个ip上的数据库能够获取数据。javax.sql.DataSource接口表示数据源,提供了标准的方法获取与数据库绑定的连接对象(Connection)。

javax.sql.Connection是连接对象,在Connection上能够从程序代码发送查询命令,更新数据的语句给数据库;同时从Connection获取命令的执行结果。Connection很重要,像一个电话线把应用程序和数据库连接起来。

 DataSource在application配置文件中以spring.datasource.*作为配置项。类似下面的代码:

spring.datasource.url=jdbc:mysql://localhost/mydb
spring.datasource.username=dbuser
spring.datasource.password=dbpass

DataSourceProperties.java是数据源的配置类,更多配置参考这个类的属性。

@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties implements BeanClassLoaderAware, InitializingBean {
}

Spring Boot能够从spring.datasource.url推断所使用的数据驱动类,如果需要特殊指定请设置spring.datasource.driver-class-name为驱动类的全限定名称。

Spring Boot支持多种数据库连接池,优先使用 HikariCP,其次是Tomcat pooling,再次是 Commons DBCP2,如果以上都没有,最后会使用Oracle UCP连接池。当项目中starter依赖了spring-boot-starter-jdbc 或者spring-boot-starter-data-jpa默认添加HikariCP连接池依赖,也就是默认使用HikariCP连接池。 

4.2 轻量的JdbcTemplate 

使用JdbcTemplate我们提供自定义SQL, Spring执行这些SQL得到记录结果集。JdbcTemplate和NamedParameterJdbcTemplate类是自动配置的,您可以@Autowire注入到自己的Bean中。开箱即用。

JdbcTemplate执行完整的SQL语句,我们将SQL语句拼接好,交给JdbcTemplate执行,JdbcTemplate底层就是使用JDBC执行SQL语句。是JDBC的封装类而已。

NamedParameterJdbcTemplate可以在SQL语句部分使用“:命名参数”作为占位符, 对参数命名,可读性更好。NamedParameterJdbcTemplate包装了JdbcTemplate对象,“:命名参数”解析后,交给JdbcTemplate执行SQL语句。

JdbcTemplateAutoConfiguration自动配置了JdbcTemplate对象,交给JdbcTemplateConfiguration创建了JdbcTemplate对象。并对JdbcTemplate做了简单的初始设置(QueryTimeout,maxRows等)。

4.2.1 准备环境 

 访问数据库先准备数据库的script。SpringBoot能够自动执行DDL,DML脚本。两个脚本文件名称默认是schema.sql和data.sql。脚本文件在类路径中自动加载。

自动执行脚本还涉及到spring.sql.init.mode配置项:

  • always:总是执行数据库初始化脚本
  • never:禁用数据库初始化 

更进一步 

Spring Boot处理特定的数据库类型,为特定的数据库定制script文件。首先设置spring.sql.init.platform=hsqldb、h2、oracle、mysql、postgresql等等,其次准备 schema-${platform}. sql 、 data-${platform}. sql 脚本文件。 

4.2.1.1  准备数据库和表脚本

首先创建数据库,安装MySQL8.5。有可用的MySQL数据库就可以,最好是5以上版本。

数据库名称Blog , 表目前使用一个 article(文章表),初始两条数据。

schema.sql 

CREATE TABLE `article` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `user_id` int(11) NOT NULL COMMENT '作者ID',
  `title` varchar(100) NOT NULL COMMENT '文章标题',
  `summary` varchar(200) DEFAULT NULL COMMENT '文章概要',
  `read_count` int(11) unsigned zerofill NOT NULL COMMENT '阅读读数',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  `update_time` datetime NOT NULL COMMENT '最后修改时间',
  PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;

data.sql 

INSERT INTO `article` VALUES ('1','2101','SpringBoot核心注解',
'核心注解的主要作用','00000008976','2023-01-16 12:11:12','2023-01-16 12:11:19');
INSERT INTO `article` VALUES ('2','356752','JVM调优',
'HotSpot虚拟机详解','00000000026','2023-01-16 12:15:27','2023-01-16 12:15:30');

4.2.1.2  创建Spring Boot工程

 新建Spring Boot工程Lession09-JdbcTemplate

构建工具:Maven

包名:com.bjpowernode.jdbc

JDK:19

Starter依赖:Lombok,MySQL Driver, JDBC API

Maven依赖(pom.xml) 

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

<dependency>
  <groupId>com.mysql</groupId>
  <artifactId>mysql-connector-j</artifactId>
  <scope>runtime</scope>
</dependency>

<dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
  <optional>true</optional>
</dependency>

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
   <scope>test</scope>
</dependency>


IDEA Maven Tool查看依赖列表

 依赖包含了连接池com.zaxxer:HikariCP:5.0.1 ,  spring-jdbc 6.0.3 , mysql驱动mysql-connector-j 8.0.31。

4.2.2 JdbcTemplate访问MySQL 

项目中依赖了spring-jdbc 6.0.3,JdbcTemplate对象会自动创建好。把JdbcTemplate对象注入给你的Bean,再调用JdbcTemplate的方法执行查询,更新,删除的SQL。

JdbcTemplate上手快,功能非常强大。提供了丰富、实用的方法,归纳起来主要有以下几种类型的方法:

  1. execute方法:可以用于执行任何SQL语句,常用来执行DDL语句。
  2. update、batchUpdate方法:用于执行新增、修改与删除等语句。
  3. query和queryForXXX方法:用于执行查询相关的语句。
  4. call方法:用于执行数据库存储过程和函数相关的语句。 

我们在2.2.1.2已经创建了Spring Boot工程,在工程上继续添加代码,完成对Blog库,article表的CRUD。 

step1:将schema.sql , data.sql拷贝到resources目录 

 step2:修改application.properties

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/blog?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false

spring.datasource.username=root
spring.datasource.password=123456
#总是执行数据库脚本,以后设置为never
spring.sql.init.mode=always

step3: 创建实体类 ArticlePO

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ArticlePO {
  private Integer id;
  private Integer userId;
  private String title;
  private String summary;
  private Integer readCount;
  private LocalDateTime createTime;
  private LocalDateTime updateTime;
}


Lomok注解给类的属性生成set,get方法。 默认和所有参数构造方法

step4: 单元测试,注入JdbcTemplate对象 

@SpringBootTest
public class TestJdbcTemplate {
  @Resource
   private JdbcTemplate jdbcTemplate;
}

测试聚合函数

@Test
void testCount() {
    String sql="select count(*) as ct from article";
    Long count = jdbcTemplate.queryForObject(sql, Long.class);
System.out.println("文章总数 = " + count);  
}

 测试“?”占位符

@Test
void testQuery() {
    // ?作为占位符
    String sql = "select * from article where id= ? ";
    //BeanPropertyRowMapper 将查询结果集,列名与属性名称匹配, 名称完全匹配或驼峰
    ArticlePO article = jdbcTemplate.queryForObject(sql,
        new BeanPropertyRowMapper<>(ArticlePO.class), 1 );
System.out.println("查询到的文章 = " + article); 
}

测试自定义RowMapper

@Test
void testQueryRowMapper() {
  //只能查询出一个记录,查询不出记录抛出异常
    String sql = "select * from article where id= " + 1;
    ArticlePO article = jdbcTemplate.queryForObject(sql, (rs, rownum) -> {
      var id = rs.getInt("id");
      var userId = rs.getInt("user_id");
      var title = rs.getString("title");
      var summary = rs.getString("summary");
      var readCount = rs.getInt("read_count");
      var createTime = new Timestamp(rs.getTimestamp("create_time").getTime())
.toLocalDateTime();
      var updateTime = new Timestamp(rs.getTimestamp("update_time").getTime())
.toLocalDateTime();
      return new ArticlePO(id, userId, title, summary, readCount,
                          createTime, updateTime);    
});
System.out.println("查询的文章 = " + article);
}


测试List集合

@Test
void testList() {
    String sql="select * from article  order by id ";
    List<Map<String, Object>> listMap = jdbcTemplate.queryForList(sql);
    listMap.forEach( el->{
        el.forEach( (field,value)->{        
System.out.println("字段名称:"+field+",列值:"+value);      
});
        System.out.println("===================================");    
});
}

测试更新记录

@Test
void testUpdate() {
    String sql="update article set title = ? where id= ? ";
    //参数是从左往右 第一个,第二个...
int updated = jdbcTemplate.update(sql, "Java核心技术思想", 2);    
System.out.println("更新记录:"+updated);  
}

4.2.3 NamedParameterJdbcTemplate

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

牛仔码农@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值