Mybatis入门、操作数据、配置xml映射、数据封装

Mybatis入门、操作数据、配置xml映射、数据封装

    • [1. MyBatis介绍、作用、相比JDBC的优势](#1. MyBatis介绍、作用、相比JDBC的优势)
      • [1.1 什么是MyBatis?](#1.1 什么是MyBatis?)
      • [1.2 MyBatis的核心作用](#1.2 MyBatis的核心作用)
      • [1.3 相比JDBC的优势(用"做饭"类比)](#1.3 相比JDBC的优势(用"做饭"类比))
    • [2. MyBatis入门实战](#2. MyBatis入门实战)
      • [2.1 准备工作(以"图书馆借阅系统"为例)](#2.1 准备工作(以"图书馆借阅系统"为例))
        • [2.1.1 数据库连接配置(application.properties)](#2.1.1 数据库连接配置(application.properties))
        • [2.1.2 创建实体类(Book.java)](#2.1.2 创建实体类(Book.java))
      • [2.2 创建Mapper接口(BookMapper.java)](#2.2 创建Mapper接口(BookMapper.java))
      • [2.3 实现查询方法(两种方式)](#2.3 实现查询方法(两种方式))
      • [2.4 IDEA配置SQL识别(避免红色警告)](#2.4 IDEA配置SQL识别(避免红色警告))
      • [2.5 日志输出配置](#2.5 日志输出配置)
    • [3. 数据库连接池详解](#3. 数据库连接池详解)
      • [3.1 什么是连接池?(用"奶茶店"类比)](#3.1 什么是连接池?(用"奶茶店"类比))
      • [3.2 主流连接池对比](#3.2 主流连接池对比)
      • [3.3 切换为Druid连接池(以"换用更智能的奶茶机"为例)](#3.3 切换为Druid连接池(以"换用更智能的奶茶机"为例))
        • [3.3.1 添加依赖(pom.xml)](#3.3.1 添加依赖(pom.xml))
        • [3.3.2 修改配置(application.properties)](#3.3.2 修改配置(application.properties))
    • [4. 删除数据操作](#4. 删除数据操作)
      • [4.1 基础删除案例(删除过期优惠券)](#4.1 基础删除案例(删除过期优惠券))
      • [4.2 #{}与{}的区别(用"快递签收"类比)](#{}与{}的区别(用"快递签收"类比))
    • [4.3 动态条件删除(用"清理衣柜"举例)](#4.3 动态条件删除(用"清理衣柜"举例))
    • [5. 新增和更新数据操作](#5. 新增和更新数据操作)
      • [5.1 新增数据(以"添加新会员"为例)](#5.1 新增数据(以"添加新会员"为例))
        • [5.1.1 封装对象入参](#5.1.1 封装对象入参)
        • [5.1.2 获取自增ID(像给新会员自动分配卡号)](#5.1.2 获取自增ID(像给新会员自动分配卡号))
      • [5.2 更新数据(以"修改收货地址"为例)](#5.2 更新数据(以"修改收货地址"为例))
        • [5.2.1 全字段更新(替换整个地址)](#5.2.1 全字段更新(替换整个地址))
        • [5.2.2 选择性更新(只改部分字段)](#5.2.2 选择性更新(只改部分字段))
    • [6. 查询数据操作与@Param注解](#6. 查询数据操作与@Param注解)
    • [7. MyBatis-XML映射配置详解](#7. MyBatis-XML映射配置详解)
      • [7.1 XML映射三大规范(用"钥匙开锁"类比)](#7.1 XML映射三大规范(用"钥匙开锁"类比))
      • [7.2 XML映射的使用场景](#7.2 XML映射的使用场景)
      • [7.3 自定义XML文件存放路径(解决"文件乱放找不到"问题)](#7.3 自定义XML文件存放路径(解决"文件乱放找不到"问题))
      • [7.4 高级案例:多表关联查询(以"查询订单及商品信息"为例)](#7.4 高级案例:多表关联查询(以"查询订单及商品信息"为例))
        • [7.4.1 定义结果映射(ResultMap)](#7.4.1 定义结果映射(ResultMap))
        • [7.4.2 编写关联查询SQL](#7.4.2 编写关联查询SQL)
      • [7.5 常见问题解决:XML文件找不到的排查步骤](#7.5 常见问题解决:XML文件找不到的排查步骤)
    • [8. 数据自动封装与类型不一致解决方案](#8. 数据自动封装与类型不一致解决方案)
      • [8.1 自动封装的默认规则("钥匙开锁"原理)](#8.1 自动封装的默认规则("钥匙开锁"原理))
      • [8.2 三种解决方案(用"快递分拣"类比)](#8.2 三种解决方案(用"快递分拣"类比))
        • [8.2.1 方式一:@Results手动映射("人工分拣")](#8.2.1 方式一:@Results手动映射("人工分拣"))
        • [8.2.2 方式二:SQL别名映射("贴标签分拣")](#8.2.2 方式二:SQL别名映射("贴标签分拣"))
        • [8.2.3 方式三:开启驼峰命名("自动翻译机")](#8.2.3 方式三:开启驼峰命名("自动翻译机"))
      • [8.3 三种方式对比与选择建议](#8.3 三种方式对比与选择建议)
      • [8.4 实战案例:混合使用三种方式](#8.4 实战案例:混合使用三种方式)

1. MyBatis介绍、作用、相比JDBC的优势

1.1 什么是MyBatis?

MyBatis是一款优秀的持久层框架 ,它支持自定义SQL、存储过程以及高级映射。可以将Java对象中的数据自动映射到数据库表中,也能将查询结果转换为Java对象,就像快递柜系统------帮你管理数据的"存取",无需手动处理复杂的数据库操作。

1.2 MyBatis的核心作用

  • 简化数据库操作:不用手动编写JDBC代码(加载驱动、创建连接、处理结果集等)
  • SQL与代码分离:SQL语句写在配置文件中,便于维护和优化
  • 自动映射:Java对象与数据库表字段自动对应,减少重复代码

1.3 相比JDBC的优势(用"做饭"类比)

场景 JDBC方式(自己做饭) MyBatis方式(点外卖)
代码量 需要写10行代码(买菜、洗菜、烹饪) 只需1行代码(下单)
维护性 修改SQL需改Java代码(改菜谱需重学) SQL单独存放(换菜品直接备注)
安全性 需手动处理SQL注入(自己防骗) 内置参数预编译(平台自动安检)
性能优化 需手动实现连接池(自己买车库) 内置连接池管理(外卖小哥调度系统)

2. MyBatis入门实战

2.1 准备工作(以"图书馆借阅系统"为例)

需求 :查询读者借阅的图书信息
技术栈:Spring Boot + MyBatis + MySQL

2.1.1 数据库连接配置(application.properties)
properties 复制代码
# 数据库连接信息(像图书馆的地址和门禁密码)
spring.datasource.url=jdbc:mysql://localhost:3306/library?useSSL=false&serverTimezone=UTC
spring.datasource.username=root       # 数据库用户名(图书管理员账号)
spring.datasource.password=123456     # 数据库密码(管理员密码)
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# MyBatis配置
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl  # 日志输出(监控借阅记录)
2.1.2 创建实体类(Book.java)
java 复制代码
public class Book {
    private Integer id;         // 图书ID(像图书的条形码)
    private String name;        // 书名("Java编程思想")
    private String author;      // 作者("Bruce Eckel")
    private Integer borrowDays; // 借阅天数(7天)
    
    // Getter和Setter方法(相当于图书信息的"查看"和"修改"功能)
    public Integer getId() { return id; }
    public void setId(Integer id) { this.id = id; }
    // 省略其他getter/setter...
}

2.2 创建Mapper接口(BookMapper.java)

java 复制代码
@Mapper  // 告诉MyBatis这是数据访问接口(图书管理员工作台)
public interface BookMapper {
    // 查询指定读者的借阅图书(根据读者ID查图书)
    List<Book> getBooksByReaderId(@Param("readerId") Integer readerId);
}

2.3 实现查询方法(两种方式)

方式一:注解方式(简单SQL)
java 复制代码
@Select("SELECT * FROM book WHERE reader_id = #{readerId}")  // SQL语句(查询命令)
List<Book> getBooksByReaderId(@Param("readerId") Integer readerId);
方式二:XML配置方式(复杂SQL)

创建BookMapper.xml文件:

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">

<!-- namespace必须和Mapper接口全类名一致 -->
<mapper namespace="com.example.library.mapper.BookMapper">
    <!-- id必须和接口方法名一致 -->
    <select id="getBooksByReaderId" resultType="com.example.library.entity.Book">
        SELECT id, name, author, borrow_days 
        FROM book 
        WHERE reader_id = #{readerId}  <!-- #{readerId}是安全的参数占位符 -->
    </select>
</mapper>

2.4 IDEA配置SQL识别(避免红色警告)

  1. 打开IDEA设置 File > Settings > Plugins
  2. 安装MyBatisX插件(像给IDE装"图书分类识别系统")
  3. 右键Mapper接口 > MyBatis > Generate Mapper XML自动生成XML文件

2.5 日志输出配置

application.properties中添加:

properties 复制代码
# 打印SQL执行日志(相当于图书馆的监控录像)
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

效果:控制台会显示执行的SQL语句和参数,例如:

复制代码
==>  Preparing: SELECT * FROM book WHERE reader_id = ? 
==> Parameters: 1001(Integer)
<==    Columns: id, name, author, borrow_days
<==        Row: 1, Java编程思想, Bruce Eckel, 7

3. 数据库连接池详解

3.1 什么是连接池?(用"奶茶店"类比)

  • 传统方式:来一个顾客开一个新锅煮奶茶(每次请求创建新数据库连接)→ 效率低
  • 连接池方式:提前煮好10锅奶茶(创建10个连接)→ 顾客直接取用,喝完放回(连接复用)

3.2 主流连接池对比

连接池 特点(用汽车类比) 适用场景
HikariCP 速度快(赛车),Spring Boot默认 高并发系统(外卖高峰期)
Druid 功能全(SUV),有监控和防SQL注入 企业级应用(物流调度中心)

3.3 切换为Druid连接池(以"换用更智能的奶茶机"为例)

3.3.1 添加依赖(pom.xml)
xml 复制代码
<!-- Druid连接池依赖(相当于买新奶茶机) -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.2.8</version>
</dependency>
3.3.2 修改配置(application.properties)
properties 复制代码
# 切换为Druid连接池(指定使用新奶茶机)
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource

# Druid特有配置(奶茶机参数)
spring.datasource.druid.initial-size=5       # 初始连接数(开机预热5锅)
spring.datasource.druid.max-active=20        # 最大连接数(最多同时煮20锅)
spring.datasource.druid.min-idle=5           # 最小空闲连接(保底5锅)
spring.datasource.druid.test-on-borrow=true  # 借连接时检测可用性(出杯前尝一口)

4. 删除数据操作

4.1 基础删除案例(删除过期优惠券)

需求 :删除超过30天未使用的优惠券
Mapper接口

java 复制代码
public interface CouponMapper {
    // 无返回值方式(像扔垃圾,不需要知道扔了多少)
    void deleteExpiredCoupons(@Param("days") Integer days);
    
    // 有返回值方式(像清点垃圾,返回删除数量)
    int deleteExpiredCouponsWithCount(@Param("days") Integer days);
}

XML映射

xml 复制代码
<!-- 无返回值删除 -->
<delete id="deleteExpiredCoupons">
    DELETE FROM coupon 
    WHERE create_time < DATE_SUB(NOW(), INTERVAL #{days} DAY)
</delete>

<!-- 有返回值删除(返回影响行数) -->
<delete id="deleteExpiredCouponsWithCount">
    DELETE FROM coupon 
    WHERE create_time < DATE_SUB(NOW(), INTERVAL #{days} DAY)
</delete>

4.2 #{}与${}的区别(用"快递签收"类比)

占位符 原理(签收方式) 安全性 使用场景举例
#{} 预编译处理(快递柜代收,验货后签收) 安全(防SQL注入) 传递参数(用户ID、订单号)
${} 字符串拼接(直接交给收件人,不验货) 不安全(可能收到炸弹) 动态表名(SELECT * FROM ${tableName}

危险示例:使用${}接收用户输入

java 复制代码
// 用户输入:1; DROP TABLE user; (恶意代码)
String sql = "SELECT * FROM user WHERE id = ${id}"; 
// 拼接后变成:SELECT * FROM user WHERE id = 1; DROP TABLE user; (删库!)

4.3 动态条件删除(用"清理衣柜"举例)

需求:根据季节和颜色删除旧衣服

xml 复制代码
<delete id="deleteClothes">
    DELETE FROM clothes 
    WHERE 1=1  <!-- 恒真条件,方便拼接AND -->
    <if test="season != null">AND season = #{season}</if>  <!-- 如:season = 'summer' -->
    <if test="color != null">AND color = #{color}</if>    <!-- 如:color = 'red' -->
</delete>

调用方式:删除所有红色夏装

java 复制代码
clothesMapper.deleteClothes("summer", "red");

5. 新增和更新数据操作

5.1 新增数据(以"添加新会员"为例)

5.1.1 封装对象入参

实体类

java 复制代码
public class Member {
    private String name;    // 姓名("张三")
    private Integer age;    // 年龄(25)
    private String phone;   // 电话("13800138000")
    
    // Getter/Setter省略
}

Mapper接口

java 复制代码
// 添加会员(参数是Member对象)
int addMember(Member member);

XML配置

xml 复制代码
<insert id="addMember">
    INSERT INTO member(name, age, phone) 
    VALUES(#{name}, #{age}, #{phone})  <!-- 直接使用对象属性名 -->
</insert>

调用方式

java 复制代码
Member newMember = new Member();
newMember.setName("张三");
newMember.setAge(25);
newMember.setPhone("13800138000");
memberMapper.addMember(newMember);  // 像把填好的会员表交给前台
5.1.2 获取自增ID(像给新会员自动分配卡号)
xml 复制代码
<insert id="addMember" useGeneratedKeys="true" keyProperty="id">
    <!-- useGeneratedKeys:使用自增主键 -->
    <!-- keyProperty:将生成的ID赋值给对象的id属性 -->
    INSERT INTO member(name, age) VALUES(#{name}, #{age})
</insert>

调用后获取ID

java 复制代码
memberMapper.addMember(newMember);
System.out.println(newMember.getId());  // 输出:10086(自动生成的ID)

5.2 更新数据(以"修改收货地址"为例)

5.2.1 全字段更新(替换整个地址)
xml 复制代码
<update id="updateAddress">
    UPDATE user 
    SET province=#{province}, city=#{city}, street=#{street}
    WHERE id=#{userId}
</update>
5.2.2 选择性更新(只改部分字段)
xml 复制代码
<update id="updateAddressSelective">
    UPDATE user 
    <set>  <!-- set标签自动处理逗号 -->
        <if test="province != null">province=#{province},</if>
        <if test="city != null">city=#{city},</if>
        <if test="street != null">street=#{street}</if>
    </set>
    WHERE id=#{userId}
</update>

优势:只更新不为null的字段(改城市时不影响省份和街道)

6. 查询数据操作与@Param注解

6.1 传递多个参数的三种方式

方式一:使用@Param注解(推荐)
java 复制代码
// 查询"张三"在"2023年"的订单(两个独立参数)
List<Order> getOrders(
    @Param("username") String username,  // 显式命名参数
    @Param("year") String year
);
xml 复制代码
<select id="getOrders" resultType="Order">
    SELECT * FROM order 
    WHERE username = #{username} 
    AND create_time LIKE CONCAT(#{year}, '%')  <!-- 如:2023% -->
</select>
方式二:使用Map传递参数(适合参数多的场景)
java 复制代码
Map<String, Object> params = new HashMap<>();
params.put("username", "张三");
params.put("year", "2023");
List<Order> orders = orderMapper.getOrdersByMap(params);
方式三:封装对象(适合参数有逻辑关联的场景)
java 复制代码
public class OrderQuery {
    private String username;
    private String year;
    // Getter/Setter
}
List<Order> getOrdersByObject(OrderQuery query);

6.2 @Param注解的强制使用场景

场景一:非Spring Boot官方骨架(如阿里云Spring Boot)
  • 原因:这些骨架可能没有配置MyBatis的参数自动命名功能,导致多参数无法识别
  • 解决:必须加@Param注解明确参数名
场景二:纯MyBatis项目(未集成Spring)
  • 原因:MyBatis原生不支持参数名自动映射,需要通过@Param指定
  • 示例
java 复制代码
// 纯MyBatis环境必须加@Param
List<User> findUsers(@Param("name") String name, @Param("age") Integer age);

7. MyBatis-XML映射配置详解

7.1 XML映射三大规范(用"钥匙开锁"类比)

  1. 同包同名 :Mapper接口和XML文件放在同一个包,文件名相同

    → 例:com.example.mapper.UserMapper.javacom.example.mapper.UserMapper.xml

  2. namespace一致:XML的namespace必须等于Mapper接口的全类名

    xml 复制代码
    <!-- 正确 -->
    <mapper namespace="com.example.mapper.UserMapper">
    <!-- 错误:namespace与接口名不符 -->
    <mapper namespace="com.example.dao.UserDao">
  3. SQL id与方法名一致:XML中SQL语句的id必须等于接口中的方法名

    xml 复制代码
    <!-- 正确:对应UserMapper接口的getUserById方法 -->
    <select id="getUserById" resultType="User">
    <!-- 错误:id与方法名不符 -->
    <select id="selectUser" resultType="User">

7.2 XML映射的使用场景

场景 适合方式 原因分析
简单SQL(单表CRUD) 注解方式 代码集中,直观简洁
复杂SQL(多表关联、动态SQL) XML方式 SQL与Java代码分离,便于维护
需要团队协作编写SQL XML方式 DBA可直接修改XML文件

7.3 自定义XML文件存放路径(解决"文件乱放找不到"问题)

问题场景

如果不按规范放(如XML文件想放resources/mapper目录下),MyBatis会找不到XML文件

解决方法:配置mapper-locations

在application.properties中添加:

properties 复制代码
# 指定XML文件存放路径(classpath表示resources目录)
mybatis.mapper-locations=classpath:mapper/*.xml

目录结构

复制代码
src/main/resources/
└── mapper/
    ├── UserMapper.xml
    └── OrderMapper.xml

7.4 高级案例:多表关联查询(以"查询订单及商品信息"为例)

7.4.1 定义结果映射(ResultMap)
xml 复制代码
<resultMap id="OrderAndProductMap" type="OrderVO">
    <!-- 订单表字段 -->
    <id property="orderId" column="order_id"/>
    <result property="orderTime" column="order_time"/>
    
    <!-- 关联商品表(一对一) -->
    <association property="product" javaType="Product">
        <id property="productId" column="product_id"/>
        <result property="productName" column="product_name"/>
    </association>
</resultMap>
7.4.2 编写关联查询SQL
xml 复制代码
<select id="getOrderWithProduct" resultMap="OrderAndProductMap">
    SELECT 
        o.id as order_id, o.time as order_time,
        p.id as product_id, p.name as product_name
    FROM `order` o
    LEFT JOIN product p ON o.product_id = p.id
    WHERE o.id = #{orderId}
</select>

7.5 常见问题解决:XML文件找不到的排查步骤

  1. 检查文件名:确保XML文件名与接口名完全一致(含大小写)
  2. 检查路径:确认XML文件在resources目录下,且与配置的mapper-locations匹配
  3. Maven打包检查:在pom.xml中添加资源文件打包配置(防止XML被过滤)
xml 复制代码
<build>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <includes>
                <include>**/*.xml</include>  <!-- 确保XML被打包 -->
            </includes>
        </resource>
    </resources>
</build>

8. 数据自动封装与类型不一致解决方案

8.1 自动封装的默认规则("钥匙开锁"原理)

MyBatis的数据封装就像钥匙匹配锁芯 ------数据库列名 必须与实体类属性名完全一致 才能自动映射。
示例

  • 数据库表字段:user_name(下划线命名)
  • 实体类属性:userName(驼峰命名)
    默认不匹配 :MyBatis找不到对应的属性,封装结果为null

8.2 三种解决方案(用"快递分拣"类比)

8.2.1 方式一:@Results手动映射("人工分拣")

适用场景 :字段名与属性名差异大(如u_iduserId
实现步骤

  1. 在Mapper接口方法上添加@Results注解
  2. @Result指定列名与属性名的对应关系

代码示例(查询用户信息):

java 复制代码
@Select("SELECT u_id, u_name, u_age FROM t_user WHERE u_id = #{id}")
@Results({
    @Result(column = "u_id", property = "userId"),    // 列u_id → 属性userId
    @Result(column = "u_name", property = "userName"),// 列u_name → 属性userName
    @Result(column = "u_age", property = "userAge")   // 列u_age → 属性userAge
})
User getUserById(Integer id);

优点 :灵活性高,可自定义映射规则
缺点:代码冗余,每个方法需单独配置

8.2.2 方式二:SQL别名映射("贴标签分拣")

适用场景 :少量字段不一致,临时调整
实现步骤 :在SQL中用AS关键字为列名起别名,使其与属性名一致

代码示例

xml 复制代码
<select id="getUser" resultType="User">
    SELECT 
        u_id AS userId,    <!-- 别名userId匹配实体类属性 -->
        u_name AS userName,
        u_age AS userAge
    FROM t_user 
    WHERE u_id = #{id}
</select>

生活类比:给快递包裹贴上新标签(别名),确保快递员(MyBatis)能正确识别目的地

8.2.3 方式三:开启驼峰命名("自动翻译机")

适用场景 :数据库列名用下划线(如user_name),实体类用驼峰命名(userName)的统一规则场景
实现步骤 :在application.properties中添加全局配置

properties 复制代码
# 开启下划线转驼峰命名(如user_name → userName)
mybatis.configuration.map-underscore-to-camel-case=true

效果:自动映射以下场景

  • 数据库列:order_id → 实体类属性:orderId
  • 数据库列:create_time → 实体类属性:createTime

注意 :需保证列名和属性名的核心部分一致(如order_idorderId的"order"部分匹配)

8.3 三种方式对比与选择建议

解决方式 配置复杂度 适用场景 维护成本
手动映射 字段名与属性名差异大(如u_id→userId) 高(每个方法单独维护)
SQL别名 少量字段不一致,临时调整 中(SQL中维护别名)
驼峰命名 极低 统一使用下划线/驼峰命名规则 低(全局配置)

选择建议

  • 新项目:优先使用驼峰命名(一劳永逸)
  • 老项目:少量字段用SQL别名 ,大量不匹配用手动映射
  • 特殊场景(如列名含缩写):必须用手动映射

8.4 实战案例:混合使用三种方式

需求:查询订单信息,包含以下字段映射

  • o_idorderId(手动映射)
  • order_snorderSn(驼峰命名,需开启配置)
  • total_amttotalAmount(SQL别名)

实现步骤

  1. 开启驼峰命名配置
  2. Mapper接口方法:
java 复制代码
@Select("SELECT o_id, order_sn, total_amt AS totalAmount FROM t_order WHERE o_id = #{id}")
@Results({
    @Result(column = "o_id", property = "orderId")  // 手动映射特殊字段
})
Order getOrderById(Integer id);

解析

  • o_idorderId:手动映射(因"o_"前缀无法通过驼峰转换)
  • order_snorderSn:驼峰命名自动转换(o_sn→orderSn)
  • total_amt AS totalAmount:SQL别名映射

通过这种混合方式,灵活处理各种映射场景。

相关推荐
微笑伴你而行20 小时前
目标检测如何将同时有方形框和旋转框的json/xml标注转为txt格式
xml·目标检测·json
javadaydayup1 天前
为什么 MyBatis Mapper 接口能像普通 Bean 一样被 @Autowired?
后端·mybatis
fatiaozhang95271 天前
数码视讯TR100-OTT-G1_国科GK6323_安卓9_广东联通原机修改-TTL烧录包-可救砖
android·xml·电视盒子·刷机固件·机顶盒刷机
l1t1 天前
美团龙猫利用expat库实现的保存xml指定范围数据到csv的C程序
xml·c语言·解析器·expat
小趴菜不能喝2 天前
Spring boot3.x整合mybatis-plus踩坑记录
java·spring boot·mybatis
焯7592 天前
若依微服务遇到的配置问题
java·mybatis·ruoyi
l1t2 天前
DuckDB新版rusty_sheet 插件测试
xml·数据库·rust·插件·xlsx·duckdb
颜如玉3 天前
MybatisPlus Sql Inject魔法🪄
后端·mybatis·源码
叫我阿柒啊3 天前
从全栈开发到微服务架构:一位Java工程师的实战经验分享
java·ci/cd·kafka·mybatis·vue3·springboot·fullstack