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

本文深入探讨SpringBoot3中访问数据库的方法,包括JdbcTemplate与MyBatis的使用。从DataSource配置、JdbcTemplate的基础操作到高级的NamedParameterJdbcTemplate,再到MyBatis的单表操作、结果映射、SQL提供者等,逐步展开数据库访问的全貌。同时,介绍了适合的连接池选择和声明式事务管理,提供详细的步骤和示例代码,帮助开发者更好地理解和应用。
摘要由CSDN通过智能技术生成

目录

第四章 访问数据库

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

N

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值