Java访问数据库(重点:SpringBoot整合Mybatis)

目录

  • 一、通过JDBC访问数据库
    • 1、思路
    • 2、示例
    • 3、思考
  • 二、通过ORM框架访问数据库(主要是Mybatis)
    • 1、示例
      • 1.1 配置
      • 1.2 SQL写在xxxMapper.xml中:mapper/UserMapper.xml
      • 1.3 xxxMapper.xml对应的xxxMapper接口(Application通过该接口访问数据库)
      • 1.4 测试
    • 2、思考
  • 三、SpringBoot整合Mybatis
    • 1、引入依赖
      • 1.1 为什么需要引入spring-boot-starter-parent?(不引入会出现什么问题?)
      • 1.2 引入spring-boot-starter-parent(进行依赖管理)
    • 2、写配置文件
      • 2.1 application.properties
        • 2.1.1 使用Spring Boot的默认配置
    • 3、xxxDO、xxxMapper.xml、xxxMapper.java
      • 3.1 目录结构![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/b7e8dbdae5b244be9ad02e63d48eca5b.png)
      • 3.2 UserDO
      • 3.3 UserMapper.java
      • 3.4 UserMapper.xml
    • 4、测试
      • 4.1 引入spring-boot-starter-test依赖
      • 4.2 测试类:UserMapperTest
    • 5、自定义mybatis配置
      • 5.1 mybatis-config.xml

一、通过JDBC访问数据库

1、思路

在这里插入图片描述

  • 可以把jdbc理解为访问数据库的接口,访问数据库的细节由驱动实现。驱动由数据库提供商遵守jdbc规范来实现。

2、示例

  • maven引入mysql驱动
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version>
</dependency>
  • 代码
public class MainClass {public static void main(String[] args) {try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/learn_mybatis","root", "xxx")) {PreparedStatement selectStatement = conn.prepareStatement("select * from user where id =  ?");selectStatement.setInt(1, 1);ResultSet rs = selectStatement.executeQuery();while (rs.next()) {Integer id = rs.getInt("id");String lastName = rs.getString("name");Integer age = rs.getInt("age");UserDO userDO = new UserDO().setId(id).setName(lastName).setAge(age);System.out.println(userDO);}} catch (Exception e) {e.printStackTrace();}}
}

3、思考

  • 从示例代码可知,实际开发中,直接通过JDBC进行增删改查太不方便了,例如,我们需要手动完成数据库的记录和Java实体类的映射。
  • 因此,我们迫切需要ORM(对象关系映射)框架来简化开发。

二、通过ORM框架访问数据库(主要是Mybatis)

官方文档

1、示例

框架 = 配置 + API

1.1 配置

  • src/main/resources/mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""https://mybatis.org/dtd/mybatis-3-config.dtd"><configuration><!-- 配置日志   --><settings><setting name="logImpl" value="LOG4J2"/></settings><environments default="development"><!-- 配置连接数据库的基本信息       --><environment id="development"><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/learn_mybatis"/><property name="username" value="root"/><property name="password" value="xxx"/></dataSource></environment></environments><!-- 配置映射文件(写SQL的地方)--><mappers><mapper resource="mapper/UserMapper.xml"/></mappers>
</configuration>
  • src/main/resources/log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration xmlns="http://logging.apache.org/log4j/2.0/config"><Appenders><Console name="stdout" target="SYSTEM_OUT"><PatternLayout pattern="%5level [%t] - %msg%n"/></Console></Appenders><Loggers><Logger name="com.forrest.learn.mapper.UserMapper" level="trace"/><Root level="error" ><AppenderRef ref="stdout"/></Root></Loggers></Configuration>

1.2 SQL写在xxxMapper.xml中:mapper/UserMapper.xml

  • src/main/resources/mapper/UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""https://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.forrest.learn.mapper.UserMapper"><select id="selectById" resultType="com.forrest.learn.pojo.UserDO">select id, name, age from user where id = #{id}</select>
</mapper>
  • src/main/java/com/forrest/learn/pojo/UserDO.java
@Data
@Accessors(chain = true)
public class UserDO {private Integer id;private String name;private Integer age;
}

1.3 xxxMapper.xml对应的xxxMapper接口(Application通过该接口访问数据库)

  • src/main/java/com/forrest/learn/mapper/UserMapper.java
public interface UserMapper {UserDO selectById(Integer id);
}

1.4 测试

  • src/test/java/com/forrest/learn/mapper/UserMapperTest.java
public class UserMapperTest {@Testpublic void selectById() {try (InputStream is = Resources.getResourceAsStream("mybatis-config.xml")) {SqlSessionFactoryBuilder ssfBuilder = new SqlSessionFactoryBuilder();SqlSessionFactory ssFactory = ssfBuilder.build(is);SqlSession sqlSession = ssFactory.openSession();UserMapper userMapper = sqlSession.getMapper(UserMapper.class);UserDO userDO = userMapper.selectById(1);System.out.println(userDO);} catch (IOException e) {System.out.println("读取配置文件失败, caused by " + e.getMessage());}}
}
  • 结果:
DEBUG [main] - ==>  Preparing: select id, name, age from user where id = ?
DEBUG [main] - ==> Parameters: 1(Integer)
TRACE [main] - <==    Columns: id, name, age
TRACE [main] - <==        Row: 1, 张三, 18
DEBUG [main] - <==      Total: 1
UserDO(id=1, name=张三, age=18)

2、思考

  • 上面的方式还不够方便(在增删改查前,还有一些模板代码),而实际开发中,直接注入UserMapper,就可以增删改查了,怎么实现的?

三、SpringBoot整合Mybatis

1、引入依赖

1.1 为什么需要引入spring-boot-starter-parent?(不引入会出现什么问题?)

<dependencies><!-- web开发需要 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.6.3</version></dependency><!-- 整合mybatis需要 --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.2</version></dependency><!-- mybatis驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.28</version></dependency></dependencies>
  • 两个starter会引入一堆依赖,如果没有“spring-boot-starter-parent”进行依赖管理,那么很容易导致依赖冲突:
    在这里插入图片描述

1.2 引入spring-boot-starter-parent(进行依赖管理)

<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.3</version>
</parent><dependencies><!-- web开发需要 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- 整合mybatis需要 --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.2</version></dependency><!-- mybatis驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency>
</dependencies>
  • spring-boot-starter-parent和mybatis-spring-boot-starter版本怎么选?
  • 如果用的是java8,那么可以选支持java8的最新版本。
  • spring官网,支持java8的最新版本为:Spring Boot 2.7.18
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
  • 通过官网可以找到合适的mybatis-spring-boot-starter版本:2.3.x(选最大的:2.3.2)
    在这里插入图片描述
  • 升级版本
<dependencies><!-- web开发需要 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- 整合mybatis需要 --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.3.2</version></dependency><!-- mybatis驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version></dependency>
</dependencies>
  • 升级版本后,mysql驱动必须指定版本了,估计是starter删除了对mysql驱动的依赖管理。那选什么版本呢?(8.0.33)
    在这里插入图片描述

当然了,选版本不用精细到x.y.z的z。找到符合要求的x.y,z能在maven仓库中搜到即可。

2、写配置文件

2.1 application.properties

src/main/resources/application.properties

2.1.1 使用Spring Boot的默认配置
  • 直接在application.properties(或application.yml)文件中配置数据库连接信息即可,而不用写mybatis-config.xml。
spring.datasource.url=jdbc:mysql://localhost:3306/learn_mybatis
spring.datasource.username=root
spring.datasource.password=xxx
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

当使用Spring Boot时,它会自动加载与spring.datasource.*相关的配置。数据源会自动注入到sqlSessionFactory中,而sqlSessionFactory会自动注入到Mapper中。因此,直接通过xxxMapper就能进行增删改查了。

3、xxxDO、xxxMapper.xml、xxxMapper.java

3.1 目录结构在这里插入图片描述

  • 基于"Free Mybatis Tool"生成UserDO(放model包下)、UserMapper.java(放mapper包下)、UserMapper.xml(resources/mapper)
    在这里插入图片描述
    在这里插入图片描述

检查生成的代码是否满足需求。

引入lombok(选最新版本,通常都是支持java8的)

<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.30</version>
</dependency>
  • 如果Mapper接口和Mapper XML文件放置在不同的包路径下(如上图所示),那么必须在MyBatis的配置中正确指定Mapper XML文件的位置。
  • 在Spring Boot应用中,可以通过在application.properties或application.yml中配置mybatis.mapper-locations属性来指定Mapper XML文件的位置。
mybatis.mapper-locations=classpath:mapper/*.xml

不配置的话,必须保证:Mapper接口的包路径和Mapper XML文件的路径是一致的。

3.2 UserDO

@Data
public class UserDO implements Serializable {private static final long serialVersionUID = 3178995131329607398L;private Integer id;private String name;private Integer age;
}

3.3 UserMapper.java

@Mapper
public interface UserMapper {int insert(UserDO record);int deleteById(Integer id);int update(UserDO record);UserDO selectById(Integer id);
}

3.4 UserMapper.xml

<?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.forrest.springboot.mybatis.dao.mapper.UserMapper"><resultMap id="UserMap" type="com.forrest.springboot.mybatis.dao.model.UserDO"><id column="id" jdbcType="INTEGER" property="id" /><result column="name" jdbcType="VARCHAR" property="name" /><result column="age" jdbcType="INTEGER" property="age" /></resultMap><sql id="tb">user</sql><sql id="cols_exclude_id">`name`, age</sql><sql id="cols_all">id, <include refid="cols_exclude_id" /></sql><insert id="insert" keyColumn="id" keyProperty="id" parameterType="com.forrest.springboot.mybatis.dao.model.UserDO" useGeneratedKeys="true">insert into <include refid="tb" />(<include refid="cols_exclude_id" />)values(#{name,jdbcType=VARCHAR}, #{age,jdbcType=INTEGER})</insert><delete id="deleteById" parameterType="java.lang.Integer">delete from <include refid="tb" />where id = #{id,jdbcType=INTEGER}</delete><update id="update" parameterType="com.forrest.springboot.mybatis.dao.model.UserDO">update <include refid="tb" /><set><if test="name != null">`name` = #{name,jdbcType=VARCHAR},</if><if test="age != null">age = #{age,jdbcType=INTEGER}</if></set>where id = #{id,jdbcType=INTEGER}</update><select id="selectById" parameterType="java.lang.Integer" resultMap="UserMap">select<include refid="cols_all" />from<include refid="tb" />whereid = #{id,jdbcType=INTEGER}</select>
</mapper>

我个人更喜欢这种xml的方式,java代码和sql代码分离。

4、测试

4.1 引入spring-boot-starter-test依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope>
</dependency>
  • 注意:不要同时引入junit5依赖,否则可能因为版本冲突导致报错“TestEngine with ID ‘junit-jupiter‘ failed to discover test”。
    在这里插入图片描述

4.2 测试类:UserMapperTest

src/test/java/com/forrest/springboot/mybatis/dao/mapper/UserMapperTest.java

@SpringBootTest
class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testvoid insert() {UserDO user = new UserDO();user.setName("John");user.setAge(30);userMapper.insert(user);assertNotNull(user.getId(), "Insert should generate ID");UserDO retrievedUser = userMapper.selectById(user.getId());assertNotNull(retrievedUser, "User should be retrieved after insertion");assertEquals("John", retrievedUser.getName(), "Name should match");assertEquals(30, retrievedUser.getAge(), "Age should match");}@Testvoid deleteById() {UserDO user = new UserDO();user.setName("Alice");user.setAge(25);userMapper.insert(user);Integer userId = user.getId();assertNotNull(userId, "Insert should generate ID");userMapper.deleteById(userId);UserDO deletedUser = userMapper.selectById(userId);assertNull(deletedUser, "User should be deleted");}@Testvoid update() {UserDO user = new UserDO();user.setName("Bob");user.setAge(35);userMapper.insert(user);Integer userId = user.getId();assertNotNull(userId, "Insert should generate ID");user.setName("UpdatedName");user.setAge(40);userMapper.update(user);UserDO updatedUser = userMapper.selectById(userId);assertNotNull(updatedUser, "User should exist after update");assertEquals("UpdatedName", updatedUser.getName(), "Name should be updated");assertEquals(40, updatedUser.getAge(), "Age should be updated");}@Testvoid selectById() {UserDO user = new UserDO();user.setName("Eve");user.setAge(28);userMapper.insert(user);Integer userId = user.getId();assertNotNull(userId, "Insert should generate ID");UserDO retrievedUser = userMapper.selectById(userId);assertNotNull(retrievedUser, "User should be retrieved by ID");assertEquals("Eve", retrievedUser.getName(), "Name should match");assertEquals(28, retrievedUser.getAge(), "Age should match");}
}

5、自定义mybatis配置

mybatis.config-location=classpath:mybatis/mybatis-config.xml
mybatis.mapper-locations=classpath:mybatis/mapper/*.xml
  • 为啥需要这两个?通过mybatis官方文档就知道了,需要一个配置文件和一堆映射文件。
    在这里插入图片描述
  • 为啥key是mybatis.config-location和mybatis.mapper-locations?这个要看:
    在这里插入图片描述

5.1 mybatis-config.xml

习惯将mybatis的配置文件命名为mybatis-config.xml

  • 具体怎么配置,看官方文档。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/751214.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

磁盘未格式化,数据恢复有妙招

一、初遇磁盘未格式化&#xff0c;惊慌失措 在日常生活和工作中&#xff0c;我们经常会使用各种存储设备来保存重要的文件和数据。然而&#xff0c;有时当我们尝试访问这些存储设备时&#xff0c;却会突然遇到一个令人头痛的问题——磁盘未格式化。这个突如其来的提示让我们措…

[Python初阶]2255.统计是给定字符串前缀的字符串数目

目录 2255.统计是给定字符串前缀的字符串数目 ①.题目 ②.问题分析 ③.startswith()方法理解 与 说明 Ⅰ.定义和用法 Ⅱ.语法 ④.问题解决 ⑤总结 2255.统计是给定字符串前缀的字符串数目 ①.题目 ②.问题分析 需求:统计列表words中,是字符串s的前缀的字符串的数目. 解…

接口与多态

通过接口实现多态 接口中声明若干个 bstract方法&#xff1b; 方法体的内容细节由实现接口的类去完成&#xff0c;不同的类有 不同的实现方式 → 则接口变量在回调接口方法时具有多 种形态。 用接口进行程序设计的核心思想 使用接口回调技术&#xff1a;接口变量存放实现该接口…

(学习日记)2024.03.13:UCOSIII第十五节:基于时基列表的时延操作(持续更新)

写在前面&#xff1a; 由于时间的不足与学习的碎片化&#xff0c;写博客变得有些奢侈。 但是对于记录学习&#xff08;忘了以后能快速复习&#xff09;的渴望一天天变得强烈。 既然如此 不如以天为单位&#xff0c;以时间为顺序&#xff0c;仅仅将博客当做一个知识学习的目录&a…

《LeetCode热题100》笔记题解思路技巧优化_Part_3

《LeetCode热题100》笔记&题解&思路&技巧&优化_Part_3 &#x1f60d;&#x1f60d;&#x1f60d; 相知&#x1f64c;&#x1f64c;&#x1f64c; 相识&#x1f622;&#x1f622;&#x1f622; 开始刷题链表&#x1f7e2;1. 相交链表&#x1f7e2;2. 反转链表&…

大数据数据分析-scala、IDEA、jdk之间的搭配关系

Scala主要是一门面向对象编程语言和函数式编程语言。 一、大数据框架&#xff08;处理海量/流式数据&#xff09; - ---以HADOOP 2. x为系列的大数据生态系统处理框架 离线数据分析&#xff0c;分析的数据为N1天数据 -----MapReduce 并行计算框架&#xff0c;分而治之…

数据治理系统论-结合数据要素等

什么是数据治理&#xff1f; 数据治理是指组织内外部对数据进行管理和监控的全面框架。它涵盖了数据的安全、合规性、可用性和价值最大化等方面。通过有效的数据治理&#xff0c;组织能够更好地理解其数据资产&#xff0c;并确保数据被正确地管理和利用。 数据治理的重要性 在…

django实现api接口

&#xff08;前期准备&#xff09;第一步&#xff1a;虚拟环境 在windows上使用virtualenvwrapper。 pip install virtualenvwrapper-win 接着&#xff0c;添加环境变量。 echo %WORKON_HOME% 接下来就是创建虚拟环境&#xff0c;假如创建myenv mkvirtualenv myenv 进入…

sqllab第二十八关通关笔记(附带28a)

知识点&#xff1a; union select 整体过滤 union all select 替换where id(输入)空格 过滤了&#xff0c;使用%09代替 经过不断的测试&#xff0c;发现原始语句为 where id(输入) 构造payload:id1)and%091(1 成功回显出了相关的信息 好&#xff0c;尝试进行错误注入 构造…

java虚拟机的堆核心知识介绍

Java虚拟机&#xff08;JVM&#xff09;的堆&#xff08;Heap&#xff09;是Java内存模型中一个至关重要的部分。它是运行时数据区&#xff0c;用于存储Java对象实例。堆是垃圾收集器工作的地方&#xff0c;也是Java应用程序内存管理的关键区域。在本教程中&#xff0c;我们将深…

nvm安装,nvm使用及常用命令,node版本管理

前端学习交流QQ群&#xff1a;1群&#xff1a;173683895 &#xff0c;2群: 173683866 承接项目开发&#xff0c;需求功能开发&#xff0c;博主微信号&#xff1a;Jay_09168 安装包下载地址 下载使用 安装&#xff1a; 点击 nvm-setup.exe&#xff0c;按下图步骤安装&#…

STM32系列——F103C8T6 控制SG90舵机(HAL库)

文章目录 一、舵机控制原理二、.CubeMX配置配置RCC、SYS、时钟树配置RCC配置SYS配置时钟树配置定时器产生PWM波形 Keil5代码接线图及效果如果您发现文章有错误请与我留言&#xff0c;感谢 一、舵机控制原理 舵机的控制一般需要一个20ms左右的时基脉冲&#xff0c;该脉冲的高电平…

(含链接)2024年NVIDIA GPU技术大会开发者合集(专为开发者挑选的合集)

2024年NVIDIA GPU技术大会开发者合集 我专门为开发者整理了NVIDIA GPU技术大会上专注技术的内容合集, 希望可以帮助开发者朋友们快速了解NVIDIA的最新技术. 注意:在电脑端打开更友好, 可以直接进入每一项的网页 文章目录 2024年NVIDIA GPU技术大会开发者合集如何登录和预约会…

[AutoSar]BSW_Com015 PDUR 模块配置

目录 关键词平台说明一、Abbreviations二、PduRBswModules三、PduRGeneration四、PduRDestPdus4.1 全局PDU ID和本地PDU ID 关键词 嵌入式、C语言、autosar、OS、BSW 平台说明 项目ValueOSautosar OSautosar厂商vector &#xff0c; EB芯片厂商TI 英飞凌编程语言C&#xff0…

react中setState是同步的还是异步的

首先说一下setState是同步的还是异步的&#xff1f; 1.解读 setState 工作流 接下来我们就沿着这个流程&#xff0c;逐个在源码中对号入座。首先是 setState 入口函数&#xff1a; ReactComponent.prototype.setState function (partialState, callback) {this.updater.enqu…

ThingsBoard初始化数据库Postgres

本章将介绍ThingsBoard的本地环境搭建&#xff0c;以及源码的编译安装。本机环境&#xff1a;centos7&#xff0c;docker,postgres 环境安装 开发环境要求&#xff1a; docker pcentos7 &#xff1b;docker&#xff1b;postgres: 1、使用Docker创建postgres容器化创建 docker…

JS函数知识点(复习)

在 JavaScript&#xff08;JS&#xff09;中使用函数有多种原因&#xff0c;这些原因不仅涉及到代码的组织和可读性&#xff0c;还涉及到代码的可维护性、复用性以及程序的模块化等方面。以下是一些关键的理由&#xff1a; 代码重用&#xff1a;函数允许你将一段代码块封装起来…

基于深度学习的唇语识别系统的设计与实现

概要 人工智能作为三大工程之一&#xff0c;从上个世纪至今仍然活跃于各个行业的研究与应用之中&#xff0c;应时代的热潮方向&#xff0c;本 课题主要针对深度学习技术应用于唇语识别当中&#xff0c;实现词语唇语的翻译功能。唇语识别在图像处理中一直是一个富 有挑战性的课题…

力扣59. 螺旋矩阵 II

思路&#xff1a;此题思路就是绕圈遍历&#xff0c;全靠条件处理技巧&#xff0c;重点要清楚的就是循环不变量&#xff1a;左闭右开&#xff08;即拐弯处的一个数&#xff0c;留给第二行处理&#xff09; 以下是代码随想录的作者的一张图片&#xff0c;每次for循环&#xff0c;…

使用三种方式读取文本文件

文章目录 &#x1f354;需求&#x1f384;思路⭐代码⭐效果&#x1f6f8;注意 在 Java 中&#xff0c;读取文件通常涉及以下几个步骤&#xff1a; 打开文件&#xff1a;首先需要创建一个文件对象&#xff0c;表示要读取的文件。这个文件对象可以包含文件路径、文件名等信息。 …