MyBatis操作数据库(入门)

个人主页♡喜欢做梦

欢迎 👍点赞 ➕关注 ❤️收藏 💬评论


🍨一、什么MyBatis?

🍦定义

MyBatis是一款持久层(用来操作数据库的)框架 ,主要用于Java语言开发,专注于解决数据库操作与Java对象之间的映像问题,简化JDBC(Java数据库连接)的开发流程

  • 核心思想是将SQL语句与Java代码分离,通过XML或注解的方式定义SQL,在由MyBatis自动完成Java对象与数据库记录之间的映射(即"ORM映射",Object-)

🍨二、准备工作

🍧1.引入依赖、mysql驱动包

🍧2.数据准备

🍧3.配置数据库连接字符串

yml文件

javascript 复制代码
spring:
  application:
    name: spring-mybatis-demo
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true
    username: root
    password: 111
    driver-class-name: com.mysql.cj.jdbc.Driver

properties文件

javascript 复制代码
#驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库连接的url
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/mybatis_test?
characterEncoding=utf8&useSSL=false
#连接数据库的⽤⼾名
spring.datasource.username=root
#连接数据库的密码
spring.datasource.password=root
  • 这里的用户名和密码要修改成自己的,否则无法连接到数据库。

🍧4.持久层

javascript 复制代码
@Mapper
public interface UserMapper {
    //查询注解
    @Select("select * from user_info")
    //接口定义方法:查询查询用户
    List<UserInfo> qurryAllUser();
}
  • Mybatis的持久层接口规范一般定义为XxxMapper;
  • Mapper层为接口类型;
  • 使用@Select注解,用于执行SQL语句;
  • 表名需要与数据库一致
  • 接口定义方法:返回结果类型 方法名

🍧5.单元测试

快速创建对应的单元测试

  • 在对应的名称上右键->Generate->Test->勾选

@Test

java 复制代码
@SpringBootTest
class UserMapperTest {
    @Autowired
    private UserMapper userMapper;
    @Test
    void qurryAllUser() {
        List<UserInfo> userInfos=userMapper.qurryAllUser();
        System.out.println(userInfos);
    }
}

除了@Test注解,这里还有@BeforeEach和@AfterEach注解

@BeforeEach和@AfterEach

@BeforeEach:在每个**@Test执行之前**执行,与位置无关(可以初始化代码等...)

@AfterEach:在每个**@Test执行之后**执行,与位置无关(可以清理资源)

java 复制代码
@SpringBootTest
class UserMapperTest {
    @Autowired
    private UserMapper userMapper;
    @BeforeEach
    void selectId() {
        String userName=userMapper.querryById(2);
        System.out.println(userName);
    }
    @AfterEach
    void selectId2() {
        String userName=userMapper.querryById(3);
        System.out.println(userName);
    }
    @Test
    void qurryAllUser() {
        List<UserInfo> userInfos=userMapper.qurryAllUser();
        System.out.println(userInfos);
    }
}

这里有一个问题了

明明在数据库中我是有数据的,但是为什么这里的deleteFalg、createTime、updateTime是null???

原因:UserInfo实体类中deleteFalg、createTime、updateTime与数据库表中的字段名不一致,没有进行正确的映射。

**这里提供了几种解决方案:**起别名、结果映射、开启驼峰命名

🍧6.数据库字段与实体类属性命名不一致问题的解决方案

1.起别名

javascript 复制代码
 @Select("select id,username,password,age,gender,phone," +
            "delete_flag as deleteFalg,create_Time as createTime,update_Time as updateTime" +
            " from user_info")
    List<UserInfo> qurryAllUser2();

测试

javascript 复制代码
   @Test
    void qurryAllUser2() {
        List<UserInfo> userInfoList=userMapper.qurryAllUser2();
        System.out.println(userInfoList);
    }

2.结果映射(@Results和@Rsult)

javascript 复制代码
 @Select("select id,username,password,age,gender,phone,delete_flag,create_Time ,update_Time from user_info")
    @Results({
            @Result(column="delete_flag",property="deleteFlag"),
            @Result(column="create_Time",property="createTime"),
            @Result(column="update_Time",property="updateTime"),
    })
    List<UserInfo> queryAllUser3();
  • @Results/@Result:用于指定数据库字段(colmn) 和**实体类的属性(property)**之间的映射关系;
  • 注意:是**@Results** 一个注解包裹**@Result**多个注解。

测试

javascript 复制代码
@Test
    void qurryAllUser3() {
        List<UserInfo> userInfoList=userMapper.queryAllUser3();
        System.out.println(userInfoList);
    }

结果

但是这里有一个问题,如果其他的SQL映射语句,我也需要进行deleteFalg、createFlag、updateFlag的映射呢?那我们是不是要再写一遍?那不是会造成代码冗余?

那这里有一个注解@ResultMap用来复用结果映射逻辑,减少代码冗余。

复用结果映射逻辑@ResultMap
javascript 复制代码
   @Select("select id,username,password,age,gender,phone,delete_flag,create_Time ,update_Time from user_info")
    @Results(id="resultMap",value = {
            @Result(column="delete_flag",property="deleteFlag"),
            @Result(column="create_Time",property="createTime"),
            @Result(column="update_Time",property="updateTime"),
    })
    List<UserInfo> queryAllUser3();

    @Select("select id,username,password,age,gender,phone,delete_flag," +
            "create_Time ,update_Time from user_info where username=#{username}")
    @ResultMap(value = "resultMap")
    UserInfo queryByName(String username);

测试

javascript 复制代码
@Test
    void querryByName() {
        System.out.println(userMapper.queryByName("zhaoliu"));
    }

结果

3.开启驼峰命名自动映射

在yml中进行配置

javascript 复制代码
mybatis:
  configuration:
    map-underscore-to-camel-case: true #配置驼峰自动转换
  • 作用:将xx_xx->xxXx,全局生效

无需在映射或起别名

javascript 复制代码
@Select("select id,username,password,age,gender,phone,delete_flag," +
            "create_Time ,update_Time from user_info where username=#{username}")
    UserInfo queryByName2(String username);

测试

javascript 复制代码
 @Test
    void queryByName2() {
        System.out.println(userMapper.queryByName2("zhaoliu"));
    }

结果


🍨三、配置日志的打印

yml

javascript 复制代码
mybatis:
  configuration: # 配置打印 MyBatis日志
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

再次运行之前的测试

打印日志的核心作用

  • 查看最终执行的语句及参数,验证映射和动态SQL是否正确;
  • 排查数据异常;
  • 分析执行耗时,优化性能。

🍨四、参数传递(#{})

  • 使用#{value},动态传参
  • value建议与参数名一致

🎂单个参数

javascript 复制代码
@Select("select username from user_info where id=#{id}")
    String querryById(Integer id);

🎂多个参数

javascript 复制代码
 @Select("select * from where id=#{id} and name=#{name}")
    List<UserInfo> selectIdAndName(Integer id,Integer name);

🎂参数重命名@Param

javascript 复制代码
  @Select("select username from user_info where id=#{id}")
    String querryById2(@Param("userId")Integer id);

🍨五、MyBatis的基础操作

🍰 1.增(Insert)

普通新增

javascript 复制代码
//新增:返回受影响的行数
 @Insert("Insert into user_info(username,password,age,gender,phone)" +
            "value(#{username},#{password},#{age},#{gender},#{phone})")
    Integer insertUserInfo(UserInfo userInfo);
  • 数据的添加使用@Insert注解;
  • 返回结果类型为Integer,因为新添数据,返回的是受影响的函数

测试

java 复制代码
   @Test
    void insertUserInfo() {
        UserInfo userInfo=new UserInfo();
        userInfo.setUsername("小哈");
        userInfo.setPassword("12345");
        userInfo.setAge(4);
        userInfo.setGender(1);
        userInfo.setPhone("124546572");
        userMapper.insertUserInfo(userInfo);
    }

新增并返回自增主键(options)

语法
javascript 复制代码
 @Options(useGeneratedKeys = true,keyProperty = "id")
  • useGeneratedKeys:获取自动生成主键功能,默认为false;
  • keyProperty:指定将生成的主键赋值给哪个属性(这个属性需要与实体类一致)。
原因

当操作存在关联关系的表的时候(如"订单表"和"订单项表"),订单项需要关联订单的主键作为外键。

  • 先插入订单,生成自增主键;
  • 需要立即获得这个主键,才能插入对应的订单项,否则订单项无法关联到订单。
使用
javascript 复制代码
@Options(useGeneratedKeys = true,keyProperty = "id")
    @Insert("Insert into user_info(username,password,age,gender,phone)" +
            "value(#{username},#{password},#{age},#{gender},#{phone})")
    Integer insertUserInfo(UserInfo userInfo);
测试
java 复制代码
 @Test
    void insertUserInfo() {
        UserInfo userInfo=new UserInfo();
        userInfo.setUsername("小哈");
        userInfo.setPassword("12345");
        userInfo.setAge(4);
        userInfo.setGender(1);
        userInfo.setPhone("124546572");
        userMapper.insertUserInfo(userInfo);
        System.out.println("数据id: "+userInfo.getId());
    }

🍰 2.删(delete)

删除

javascript 复制代码
@Delete("delete from user_info where username=#{username}")
    Integer deldeteUserName(String username);

测试

java 复制代码
@Test
    void deldeteUserName() {
        userMapper.deldeteUserName("小哈");
    }

🍰 3.改(update)

更新

javascript 复制代码
@Update("update user_info set username=#{username} where id=#{id}")
    Integer updateUserName(UserInfo userInfo);

测试

java 复制代码
@Test
    void updateUserName() {
        UserInfo userInfo=new UserInfo();
        userInfo.setUsername("zhaoliu");
        userInfo.setId(2);
        userMapper.updateUserName(userInfo);
    }

改前

改后

还有查找(select),我们前面也有使用到,这里就不多写了。

相关推荐
楠枬1 小时前
Spring Cloud 概述
java·spring cloud·微服务
q***d1731 小时前
微服务与单体架构的成本对比
java·微服务·架构
敲上瘾1 小时前
MySQL事务全攻略:ACID特性、隔离级别与并发控制
linux·数据库·mysql·安全
冻感糕人~1 小时前
Agent框架协议“三部曲”:MCP、A2A与AG-UI的协同演进
java·人工智能·学习·语言模型·大模型·agent·大模型学习
懒羊羊不懒@2 小时前
【MySQL | 基础】事务
数据库·mysql
阿Y加油吧2 小时前
java并发编程面试题精讲——day02
java·面试·c#
lucky_syq2 小时前
再谈向量数据库:AI时代的存储新引擎
大数据·数据库·人工智能
v***44672 小时前
【Mysql】:如何恢复误删的数据?
数据库·mysql
ArabySide2 小时前
【Spring Boot】基于MyBatis的条件分页
java·spring boot·后端·mybatis