当前位置: 首页 > news >正文

后端Web实战-Java代码操作数据库

目录

1.JDBC

1.1概述

1.2快速入门

1.3 API详解

1.3.1 DriverManager

1.3.1.1 注册驱动

1.3.1.2 获取链接

1.3.2 Connection & Statement

1.3.3 ResultSet

1.3.4 PreparedStatement

2.Mybtis基础

2.1 介绍

2.2 快速入门

2.2.1 准备工作

2.2.2 编写SQL语句

2.2.3 单元测试

2.3 辅助配置

2.3.1 配置SQL提示

2.3.2 配置Mybatis的日志输出

2.4 JDBC VS Mybatis

2.5 数据库连接池

2.5.1 介绍数据库连接池

2.5.2 如何实现数据库连接?

2.6 Mybatis的XML配置文件

2.6.1 XML配置文件规范

2.6.3 MybatisX的使用

3.部门列表查询

3.1 功能实现

3.1.1 需求

3.1.2 实现

3.2 数据封装


1.JDBC

1.1概述

我们做为后端程序开发人员,通常会使用Java程序来完成对数据库的操作。Java程序操作数据库的技术呢,有很多啊。

  • JDBC:(Java DataBase Connectivity),就是使用Java语言操作关系型数据库的一套API。 【是操作数据库最为基础、底层的技术】

那现在在企业项目开发中呢,一般都会使用基于JDBC的封装的高级框架,比如:Mybatis、MybatisPlus、Hibernate、SpringDataJPA。

我们会学习目前最为主流的就是Mybatis,其次是MybatisPlus。

JDBC:(Java DataBase Connectivity),就是使用Java语言操作关系型数据库的一套API。

本质:

  • sun公司官方定义的一套操作所有关系型数据库的规范,即接口。

  • 各个数据库厂商去实现这套接口,提供数据库驱动jar包。

  • 我们可以使用这套接口(JDBC)编程,真正执行的代码是驱动jar包中的实现类。

1.2快速入门

public class JDBCTest {@Testpublic void testUpdate() throws Exception {//1.准备工作//1.1 注册驱动Class.forName("com.mysql.cj.jdbc.Driver");//固定步骤//1.2 获取数据库连接对象ConnectionConnection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/java147_db02", "root", "456789");//1.3 获取SQL语句执行对象StatementStatement statement = connection.createStatement();//2.执行SQL语句//需求:修改用户表id为1的密码,修改为12345678int i = statement.executeUpdate("update user set password = '12345678' where id = 1;");System.out.println("i == " + i);//3.释放资源statement.close();connection.close();}
}

1.3 API详解

1.3.1 DriverManager

作用:

  • 注册驱动

  • 获取数据库链接 Connection

1.3.1.1 注册驱动

上述的代码中我们是通过class.forName("com.mysql.cj.jdbc.Driver")来注册的,看似和DriverManager没什么联系。其实不然,这段代码只是将Driver这个类加载到JVM中。而在Driver这个类中定义了静态代码块,内容如下:

Driver 这个类被加载时,就会自动执行静态代码块中的代码,然后就完成了注册驱动的操作。

备注:

而其实啊,class.forName("com.mysql.cj.jdbc.Driver") 这句代码呢,是可以省略的,省略了,也可以正常的完成驱动的注册。 原因是因为在MySQL的驱动jar包中,在 META-INF/services 目录中提供了一个文件 java.sql.Driver ,在这个文件中编写了一行内容,就是驱动类的全类名 :

当在程序需要用到这个类时,java会自动加载这个类,这个类一加载 就会自动执行静态代码块中的内容,就完成了注册驱动的操作 ,而java中的这个机制称之为 SPI

SPI机制:Service Provider Interface,JDK内置的一种服务提供发现机制,可以轻松的扩展你的程序(切换实现),实现接口与实现类之间的解耦。

1.3.1.2 获取链接

1.3.2 Connection & Statement

  • Connection的作用:获取执行SQL的对象

    • 执行普通SQL对象的Statement:connection.createStatement();

    • 执行预编译SQL对象PreparedStatement:connection.prepareStatement(); 【后面单独讲解】

  • Statement的作用:执行SQL

    • 执行DDL(数据库定义语句,一般不用)、DML(增删改)语句:executeUpdate(sql); 如果是执行DML语句完毕,返回值int代表 DML 语句影响的行数。

    • 执行SQL(查询)语句:executeQuery(sql); 返回值为ResultSet,里面封装了查询结果。

1.3.3 ResultSet

@Testpublic void testSelect() throws Exception {//1.准备工作//1.1 注册驱动//Class.forName("com.mysql.cj.jdbc.Driver");//固定步骤//省略注册驱动也可以运行成功,//1.2 获取数据库连接对象ConnectionConnection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/java147_db02", "root", "456789");//1.3 获取SQL语句执行对象StatementStatement statement = connection.createStatement();//2.执行SQL语句//需求:根据用户名和密码查询用户信息,模拟用户登录ResultSet resultSet = statement.executeQuery("select * from user where username = 'xiaoqiao' and password = '123456'");//判断是否有值while(resultSet.next()) {//输出结果--解析Resulet//int id = resultSet.getInt(1); //下标从1开始int id = resultSet.getInt("id");String username = resultSet.getString("username");String password = resultSet.getString("password");String name = resultSet.getString("name");int age = resultSet.getInt("age");User user = new User(id,username,password,name,age);System.out.println(user);}//3.释放资源statement.close();connection.close();}

在上述的单元测试中,我们在SQL语句中,将用户名和密码的值都写死了,而这两个值应该是动态的,是将来页面传递到服务端的。那么,我们可以基于前面所讲的JUnit中的参数化测试进行单元测试,代码改造如下:

 @ParameterizedTest //参数化测试//@ValueSource(strings = {"xiaoqiao","123456"}) //代表一个参数分两次测试//所以@ValueSource只适合对一个参数进行测试的@CsvSource(value = {"xiaoqiao, 123456", "zhangsan, 123456"})public void testSelect(String uname,String pwd) throws Exception {//1.准备工作//1.1 注册驱动//Class.forName("com.mysql.cj.jdbc.Driver");//固定步骤//省略注册驱动也可以运行成功,//1.2 获取数据库连接对象ConnectionConnection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/java147_db02", "root", "456789");//1.3 获取SQL语句执行对象StatementStatement statement = connection.createStatement();//2.执行SQL语句//需求:根据用户名和密码查询用户信息,模拟用户登录ResultSet resultSet = statement.executeQuery("select * from user where username = '"+uname+"' and password = '"+pwd+"'");//判断是否有值while(resultSet.next()) {//输出结果--解析Resulet//int id = resultSet.getInt(1); //下标从1开始int id = resultSet.getInt("id");String username = resultSet.getString("username");String password = resultSet.getString("password");String name = resultSet.getString("name");int age = resultSet.getInt("age");User user = new User(id,username,password,name,age);System.out.println(user);}//3.释放资源statement.close();connection.close();}

如果在测试时需要用一个参数就用@ValueSource(strings = {"xiaoqiao","123456"}) //代表一个参数分两次测试,如果需要用到一组参数就用 @CsvSource(value = {"xiaoqiao, 123456", "zhangsan, 123456"})进行注解。

1.3.4 PreparedStatement

  • 作用:预编译SQL语句并执行,可以防止SQL注入问题。

  • SQL注入:通过控制输入来修改事先定义好的SQL语句,以达到执行代码对服务器进行攻击的方法。

@ParameterizedTest //参数化测试//@ValueSource(strings = {"xiaoqiao","123456"}) //代表一个参数分两次测试//所以@ValueSource只适合对一个参数进行测试的@CsvSource(value = {"xiaoqiao, 123456", "zhangsan, ' or '1' = '1"})public void testSelect(String uname,String pwd) throws Exception {//1.准备工作//1.1 注册驱动//Class.forName("com.mysql.cj.jdbc.Driver");//固定步骤//省略注册驱动也可以运行成功,//1.2 获取数据库连接对象ConnectionConnection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/java147_db02", "root", "456789");//1.3 获取SQL语句执行对象Statement -- ?代表占位符PreparedStatement ps = connection.prepareStatement("select * from user where username = ? and password = ?");//1.4设置参数值ps.setString(1,uname);ps.setString(2,pwd);//2.执行SQL语句//需求:根据用户名和密码查询用户信息,模拟用户登录ResultSet resultSet = ps.executeQuery();//判断是否有值while(resultSet.next()) {//输出结果--解析Resulet//int id = resultSet.getInt(1); //下标从1开始int id = resultSet.getInt("id");String username = resultSet.getString("username");String password = resultSet.getString("password");String name = resultSet.getString("name");int age = resultSet.getInt("age");User user = new User(id,username,password,name,age);System.out.println(user);}//3.释放资源ps.close();connection.close();}

在预编译SQL语句中,当我们执行的时候,会把整个' or '1'='1作为一个完整的参数,赋值给第2个问号(' or '1'='1进行了转义,只当做字符串使用)

那么此时再查询时,就查询不到对应的数据了,登录失败。

注意:在以后的项目开发中,我们使用的基本全部都是预编译SQL语句。

预编译SQL的优势:

  • 安全(防止SQL注入)

  • 性能更高

PreparedStatement性能更高的主要原因与其预编译机制和数据库的执行优化有关:

1.SQL预编译与重用

PreparedStatement 会在创建时将 SQL 语句发送给数据库进行预编译(解析、优化、生成执行计划),后续执行时只需传入参数即可。
而 Statement 每次执行都需要重新发送完整 SQL、重新编译,这会产生额外的网络传输和数据库解析开销。
对于多次执行相同结构(仅参数不同)的 SQL(如批量插入、更新),PreparedStatement 的预编译结果可以重复使用,大幅减少重复工作。

2.数据库执行计划缓存

数据库通常会缓存预编译生成的执行计划,当再次执行相同 SQL 结构时,可直接复用缓存的计划,避免重复优化和计算,进一步提升效率。

3.参数高效处理

PreparedStatement 通过 setXxx() 方法设置参数,数据库会高效处理参数绑定,避免了字符串拼接 SQL 带来的额外解析成本(例如 Statement 中用 + 拼接参数的字符串操作)。

4.批量操作优化
PreparedStatement 支持 addBatch() 和 executeBatch() 进行批量操作,数据库可以对批量命令进行合并处理,减少网络交互次数和事务提交开销,这在大量数据操作时优势明显。

2.Mybtis基础

2.1 介绍

什么是MyBatis?

  • MyBatis是一款优秀的 持久层 框架,用于简化JDBC的开发。

  • MyBatis本是 Apache的一个开源项目iBatis,2010年这个项目由apache迁移到了google code,并且改名为MyBatis 。2013年11月迁移到Github。

  • 官网:https://mybatis.org/mybatis-3/zh/index.html

在上面我们提到了两个词:一个是持久层,另一个是框架。

  • 持久层:指的是就是数据访问层(dao),是用来操作数据库的。

框架:是一个半成品软件,是一套可重用的、通用的、软件基础代码模型。在框架的基础上进行软件开发更加高效、规范、通用、可拓展。

2.2 快速入门

2.2.1 准备工作

项目工程创建完成后,自动在pom.xml文件中,导入Mybatis依赖和MySQL驱动依赖

<dependencies><!-- Mybatis的起步依赖 --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>3.0.3</version></dependency><!-- MySQL驱动 --><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope></dependency><!-- lombok驱动 --><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>
</dependencies>

2.2.2 编写SQL语句

在创建出来的springboot工程中,在引导类所在包下,再创建一个包mapper。在,mapper包下创建一个接口UserMapper,这是一个持久层接口(Mybatis的持久层接口规范一般都叫XxxMapper)

UserMapper的内容如下:

import com.itheima.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;import java.util.List;@Mapper //作用:程序启动时,会自动生成该接口的的代理对象,交由IOC容器管理
public interface UserMapper {//查询所有用户数据@Select("select * from user")public List<User> list();
}

@Mapper注解:表示是mybatis中的Mapper接口,在程序运行时,框架会自动生成接口的实现类对象(代理对象),并交给Spring的IOC容器管理

@Select注解:代表的就是select查询,用于书写select查询语句

2.2.3 单元测试

在创建出来的SpringBoot工程中,在src下的test目录下,我们创建测试类UserMapperTest,并且在测试类上已经添加了注解@SpringBootTest,代表该测试类已经与SpringBoot整合。

该测试类在运行时,会自动通过引导类加载Spring的环境(IOC容器(控制反转,对象的创建控制权由程序自身转移到外部(容器),这种思想称为控制反转))。我们要测试上面的bean对象,就可以直接通过@Autowired注解直接将其注入进行,然后就可以测试了。

import com.itheima.entity.User;
import com.itheima.mappeer.UserMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;import java.util.List;@SpringBootTest //作用:会加载Spring环境(IOC容器)
public class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testpublic void testList() {List<User> list = userMapper.list();for (User user : list) {System.out.println(user);}}
}

运行结果:

<span style="background-color:#f8f8f8">User(id=1, username=daqiao, password=1234567890, name=大乔, age=22)
User(id=2, username=xiaoqiao, password=123456, name=小乔, age=18)
User(id=3, username=diaochan, password=123456, name=貂蝉, age=24)
User(id=4, username=lvbu, password=123456, name=吕布, age=28)
User(id=5, username=zhaoyun, password=12345678, name=赵云, age=27)</span>

注意:测试类所在包,需要与引导类所在包相同。

如果测试类UserMapperTest类不在com.itheima这个包下,而是被移动到了com.itbaima,此时我们需要在UserMapperTest类里加上(class = SpringbootMybatisQuickstartApplication.class)

@SpringBootTest(classes = SpringbootMybatisQuickstartApplication.class) 
//作用:会加载Spring环境(IOC容器)
//@SpringBootTest //作用:会加载Spring环境(IOC容器)
//注意:测试类所在包必须与启动类所在包或子包一致
public class UserMapperTest {@Autowiredprivate UserMapper userMapper;@Testpublic void testList() {List<User> list = userMapper.list();for (User user : list) {System.out.println(user);}}
}

2.3 辅助配置

2.3.1 配置SQL提示

默认我们在UserMapper接口上的 @Select 注解中编写SQL语句是没有提示的。如果想让idea给出提示,可以做如下配置:

配置完成之后,发现SQL语句中的关键字有提示了,但还存在不识别表名(列名)的情况:

产生原因:Idea和数据库没有建立连接,不识别表信息

解决方案:在Idea中配置MySQL数据库连接

注意:该配置的目的,仅仅是为了在编写SQL语句时,有语法提示(写错了会报错),不会影响运行,即使不配置也是可以的。

2.3.2 配置Mybatis的日志输出

默认情况下,在Mybatis中,SQL语句执行时,我们并看不到SQL语句的执行日志。 加入如下配置,即可查看日志:

打开上述开关之后,再次运行单元测试,就可以看到控制台输出的SQL语句是什么样子的。

2.4 JDBC VS Mybatis

JDBC程序的缺点:

  • url、username、password 等相关参数全部硬编码在java代码中。

  • 查询结果的解析、封装比较繁琐。

  • 每一次操作数据库之前,先获取连接,操作完毕之后,关闭连接。 频繁的获取连接、释放连接造成资源浪费。

分析了JDBC的缺点之后,我们再来看一下在mybatis中,是如何解决这些问题的:

  1. 数据库连接四要素(驱动、链接、用户名、密码),都配置在springboot默认的配置文件 application.properties中

  2. 查询结果的解析及封装,由mybatis自动完成映射封装,我们无需关注

  3. 在mybatis中使用了数据库连接池技术,从而避免了频繁的创建连接、销毁连接而带来的资源浪费。

使用SpringBoot+Mybatis的方式操作数据库,能够提升开发效率、降低资源浪费

而对于Mybatis来说,我们在开发持久层程序操作数据库时,需要重点关注以下两个方面:

1.application.properties

#驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库连接的url
spring.datasource.url=jdbc:mysql://localhost:3306/web01
#连接数据库的用户名
spring.datasource.username=root
#连接数据库的密码
spring.datasource.password=1234

2.Mapper接口(编写SQL语句)

@Mapper
public interface UserMapper {@Select("select * from user")public List<User> list();
}

2.5 数据库连接池

前面我们说过mybatis中,使用了数据库连接池技术,避免频繁的创建连接、销毁连接而带来的资源浪费

2.5.1 介绍数据库连接池

    没有使用数据库连接池:

    • 客户端执行SQL语句:要先创建一个新的连接对象,然后执行SQL语句,SQL语句执行后有需要关闭连接对象来从而释放资源,每次执行SQL时都需要创建连接、销毁连接,这种频繁的重复创建和销毁的过程是比较耗费计算机的性能的。

    使用数据库连接池,数据库连接池是一个容器,负责分配,管理数据库连接(Connection)

    • 程序在启动时,会在数据库连接池(容器)中创建一定数量的Connection对象允许应用程序重复使用一个现有的数据库连接,而不是重新创建一个
    • 客户端在执行SQL时,先从连接池中获取一个Connection对象,然后在执行SQL语句,SQL语句执行完之后,释放Connection时就会把Connection对象归还给连接池(Connection对象可以重复使用)

    数据库连接池会自动释放空闲时间超过最大空闲时间的连接,来避免因为没有释放连接而引起的数据库连接遗漏

    最大空闲时间核心作用是:规定一个连接在连接池中保持空闲状态的最长时间。当某个连接的空闲时间超过这个阈值时,连接池会自动将其关闭并从池中移除,释放相关资源。

    • 客户端获取到Connection对象了,但是Connection对象并没有去访问数据库(处于空闲),数据库连接池发现Connection对象的空闲时间 > 连接池中预设的最大空闲时间,此时数据库连接池就会自动释放掉这个连接对象

    数据库连接池的好处:

    1. 资源重用

    2. 提升系统响应速度

    3. 避免数据库连接遗漏

    2.5.2 如何实现数据库连接?

    • 官方(sun)提供了数据库连接池标准(javax.sql.DataSource接口)

                    功能:获取连接

    public Connection getConnection() throw SQLException;

    常见的数据库连接池:C3P0、DBCP、Druid、Hikari(springboot默认)

    现在更多使用的是Druid和Hikari(性能更加优越)

    1). Hikari(追光者) [默认的连接池]

    2). Druid(德鲁伊)

    • Druid连接池是阿里巴巴开源的数据库连接池项目

    • 功能强大,性能优秀,是Java语言最好的数据库连接池之一

    如果我们想把默认的数据库连接池切换为Druid数据库连接池,只需要完成一下两步操作即可:

    1.在pom.xml文件中引入依赖

    <dependency><!-- Druid连接池依赖 --><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.19</version>
    </dependency>

    2.在application.properties中引入数据库连接配置

    spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
    spring.datasource.druid.driver-class-name=com.mysql.cj.jdbc.Driver
    spring.datasource.druid.url=jdbc:mysql://localhost:3306/mybatis
    spring.datasource.druid.username=root
    spring.datasource.druid.password=1234

    2.6 Mybatis的XML配置文件

    Mybatis的开发有两种方式:

    1.注解

    2.XML

    2.6.1 XML配置文件规范

    使用Mybatis的注解方式主要是来完成一些简单的增删改查功能。如果需要实现复杂的SQL功能,建议使用XML来配置映射语句,也就是将SQL语句写在XML配置文件中。

    在Mybatis中使用XML映射文件方式开发,需要符合一定的规范:

    1. XML映射文件的名称与Mapper接口名称一致,并且将XML映射文件和Mapper接口放置在相同包下(同包同名)

    2. XML映射文件的namespace属性为Mapper接口全限定名一致

    3. XML映射文件中sql语句的id与Mapper接口中的方法名一致,并保持返回类型resultType一致。

    注意:

    • 在resources下创建文件夹要用 / 来分级创建,用点并没有分级效果。
    • 名称一致指的是全限定名一致,含包名和类名的全称
    • resultType如果有返回值就要用实体类的全称(指的是查询返回的单条记录所封装的类型,如User类),如果无返回值就不需要写

    2.6.3 MybatisX的使用

    可以通过MybatisX快速定位

    3.部门列表查询

    3.1 功能实现

    3.1.1 需求

    查询数据库表中的所有部门数据,展示在页面上

    3.1.2 实现

    1.准备数据库表dept及实体类Dept

    -- 部门管理
    create table dept(id int unsigned primary key auto_increment comment '主键ID',name varchar(10) not null unique comment '部门名称',create_time datetime  comment '创建时间',update_time datetime  comment '修改时间'
    ) comment '部门表';INSERT INTO `dept` VALUES (1,'学工部','2023-09-25 09:47:40','2023-09-25 09:47:40'),(2,'教研部','2023-09-25 09:47:40','2023-09-25 09:47:40'),(3,'咨询部','2023-09-25 09:47:40','2023-09-25 09:47:40'),(4,'就业部','2023-09-25 09:47:40','2023-09-25 09:47:40'),(5,'人事部','2023-09-25 09:47:40','2023-09-25 09:47:40'),(6,'行政部','2023-09-27 14:00:00','2023-09-27 14:00:00'),(7,'综合部','2023-09-25 14:44:19','2023-09-25 14:44:19');
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    import java.time.LocalDateTime;@Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class Dept {private Integer id;private String name;private LocalDateTime createTime;private LocalDateTime updateTime;
    }
    

    2.在项目中引入Mybatis的起步依赖,mysql的驱动包

    <dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>3.0.3</version>
    </dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope>
    </dependency>

    3.在项目的application.properties 中引入Mybatis的配置信息 (数据库连接、日志输出)

    #数据库连接信息
    spring.datasource.url=jdbc:mysql://localhost:3306/web01
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    spring.datasource.username=root
    spring.datasource.password=root@1234#mybatis 日志
    mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

    4.定义mapper包,并且定义DeptMapper接口,并声明接口方法。

    import com.itheima.pojo.Dept;
    import org.apache.ibatis.annotations.Mapper;
    import org.apache.ibatis.annotations.Select;
    import java.util.List;@Mapper
    public interface DeptMapper {@Select("select * from dept")public List<Dept> list();}

    5.改造之前编写的dao、service的代码,在service实现中注入mapper接口

    • dao层的代码不需要了(备份之后,可以删除)

    • service层的代码,需要注入Mapper接口,调用mapper接口方法查询数据库中的数据

    package com.itheima.service.impl;import com.itheima.entity.Dept;
    import com.itheima.mapper.DeptMapper;
    import com.itheima.service.DeptService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;import java.util.List;/*** 业务逻辑处理层*/@Service
    public class DeptServiceImpl implements DeptService {@Autowired //从IOC容器中,自动寻找bean对象,为该变量赋值--依赖注入DI的实现private DeptMapper deptMapper;public List<Dept> list(){//1.调用mapper的方法,获取列表数据并返回return deptMapper.list();}
    }
    

    6.启动服务,打开apifox进行测试

    经过测试,我们发现,创建时间 createTime,修改时间 updateTime 属性并未成功封装。 接下来,我们就需要来处理数据封装问题。

    3.2 数据封装

    我们看到查询返回的结果中大部分字段是有值的,但是createTime,updateTime这两个字段是没有值的,而数据库中是有对应的字段值的,这是为什么呢?

    原因:

    • 实体类属性名和数据库表查询返回的字段名一致,mybatis会自动封装。
    • 如果实体类属性名和数据库表查询返回的字段名不一致,不能自动封装。

    解决方案:

    1. 起别名

    2. 结果映射

    3. 开启驼峰命名

    package com.itheima.mapper;import com.itheima.entity.Dept;
    import org.apache.ibatis.annotations.Mapper;
    import org.apache.ibatis.annotations.Result;
    import org.apache.ibatis.annotations.Results;
    import org.apache.ibatis.annotations.Select;import java.util.List;@Mapper
    public interface DeptMapper {/*** 查询所有部门信息** @return*///数据封装方式一:手动结果映射
    //    @Results({
    //            @Result(column = "create_time", property = "createtime"),
    //            @Result(column = "update_time", property = "updatetime")
    //    })//数据封装方式二:起别名//@Select("select id, name, create_time createTime, update_time updateTime from dept")//数据封装方式三:全局配置,开启驼峰命名规则映射@Select("select * from dept")public List<Dept> list();
    }
    

    3.开启驼峰命名(推荐):如果字段名与属性名符合驼峰命名规则,mybatis会自动通过驼峰命名规则映射

    驼峰命名规则: abc_xyz => abcXyz

    • 表中字段名:abc_xyz

    • 类中属性名:abcXyz

    # 在application.properties中添加:
    mybatis.configuration.map-underscore-to-camel-case=true

    要使用驼峰命名前提是 实体类的属性 与 数据库表中的字段名严格遵守驼峰命名。

    http://www.dtcms.com/a/349098.html

    相关文章:

  1. 跨摄像头追踪精度↑79%!陌讯动态决策模型在智慧园区的落地实践
  2. 跨摄像头追踪准确率↑18%!陌讯时空感知算法在智慧安防的实战解析
  3. 复杂场景鲁棒性突破!陌讯自适应融合算法在厂区越界检测的实战优化​
  4. 使用Localtunnel搭建与外网交互简单的https本地服务器
  5. 时序数据库选型“下半场”:从性能竞赛到生态博弈,四大主流架构深度横评
  6. Windows 系统下 Android SDK 配置教程
  7. 【数据结构与算法】并查集
  8. 对象作为HashMap的key的注意事项
  9. kubernetes集群搭建
  10. 【贪心算法】day2
  11. Golang云端编程入门指南:前沿框架与技术全景解析
  12. 初探机器学习:从概念定义到前沿应用
  13. 湖南(源点咨询)市场调研如何在行业研究中快速有效介入(尾篇)
  14. mpv - write_video 流程解析
  15. 从技术精英到“芯”途末路:一位工程师的沉沦与救赎
  16. 暖色调街头人像摄影照片Lr调色教程,手机滤镜PS+Lightroom预设下载!
  17. OpenHarmony Audio子系统全栈解码:从HDI驱动到DSP算法的低延迟高保真之路
  18. SQL Server缩小日志文件.ldf的方法(适用于开发环境)
  19. 复杂水域场景识别率↑89%!陌讯多模态融合算法在岸边垃圾检测的落地实践
  20. Python学习笔记之(二)变量和简单的数据类型
  21. 鸿蒙中Image白块问题分析与解决方案
  22. Java:HashMap的使用
  23. 2025/8/24 DockerDesktop安装使用
  24. 云原生俱乐部-RH294知识点归纳(3)
  25. Python内置函数全解析:30个核心函数语法、案例与最佳实践指南
  26. Linux应急响应一般思路(二)
  27. C++测试框架高级资源管理模块完整实现指南
  28. 八、redis 入门 之 雪崩、穿透、击穿
  29. 小米AX3600访问桥接的光猫
  30. 如何一键统一文件名大小写?