快速上手mybatis(一)

目录

一:简介

1.诞生

2.mybatis了解

二:使用

1.项目环境配置

2.mapper数据库操作

1>:映射规则

2>:insert:密码等于李四的基本信息

3>:insert:一个参数的基本查找信息

4>:insert:多个参数的基本查找信息

5>:处理值不正确情况

6>:insert:一行数据

7>:insert:拿到新添加的数据

8.delete:删除一行数据

9>:update:更新一条数据

3.xml数据库操作

1>:配置与创建

2>:select:查询一条数据

3>:insert:添加一条数据

4>:update:修改值

5>:delete:删除记录

三.小总结


前言:本篇主要是简单快速上手使用为目的,讲解不是很深入

一:简介

1.诞生

传统的数据库操作,如JDBC在执行一个简单的操作,都需要写一大堆代码,大大降低了在开发环境中的工作效率,为此将传统的JDBC复杂冗余的操作进行封装---mybatis

2.mybatis了解

1>:MyBatis 是一款优秀的 Java 持久层框架(ORM 框架)

2>: 对原生 JDBC 的封装和增强,是代码与数据库之间的桥梁, 数据可以通过mybatis操作快速永久性存储在数据库中

3>:可以简化 Java 程序对数据库的 CRUD 操作,消除 JDBC 原生开发的冗余代码,同时兼顾 SQL 的灵活性

4>:mybatis的核心特点 配置映射 + 底层封装 JDBC

简单来说:开发者只需要关注「写 SQL语句」和「调用方法」,剩下的所有 JDBC 繁琐操作,MyBatis 全帮你做了

二:使用

1.项目环境配置

1>:依赖导入

在创建项目时导入:

mybatis Framework:把 MyBatis 框架引入 Spring Boot 项目,让项目能通过 MyBatis 操作数据库(写 SQL、映射数据等)

mysql driver: 是 Java 程序连接 MySQL 数据库的驱动包

pom文件依赖导入:

看自己的mybatis-spring-boot-starter版本与spring-boot版本是否匹配

对应链接:Introduction -- mybatis-spring-boot-autoconfigure

yml配置:

java 复制代码
spring:
  application:
    name: spring-batis-12-29
# 数据库连接配置
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false #连接url
    username: root # 用户名
    password: "123456" # 密码,数字加上引号
    driver-class-name: com.mysql.cj.jdbc.Driver # 驱动类型
mybatis:
  configuration: # 配置打印 MyBatis⽇志,让 MyBatis 执行的 SQL 语句打印到控制台
  log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

文件创建:

前提首先提前准备好操作的数据库

接着创建接口并添加注解

java 复制代码
@Mapper
public interface UserInfoMapper {
    // 可以书写mybatis代码
}

2.mapper数据库操作

1>:映射规则

mybatis主要作用在于映射: 会将查找的mysql按照字段名(若有下换线分割,则 去除下划线+小驼峰形式 ) ,并在java定义的类中寻找对应的相匹配的属性名进行一一赋值

比如: mysql中的字段名称为: user_name ,到java中就会找 userName字段进行赋值

特殊注意:若字段存在下换线分割时,必须添加依赖才会自动匹配--->后面会重点讲到

还要创建一个用于接受返回值的类:

java 复制代码
@Data
public class UserInfo {
    private Integer id;
    private String username;
    private String password;
    private Integer age;
    private Integer gender;
    private String phone;
    private Integer deleteFlag;
    private Date createTime;
    private Date updateTime;
}

2>: insert**:密码等于李四的基本信息**

代码:

java 复制代码
    @Select("select * from user_info where `password` = 'lisi'")
    UserInfo selectByPass();

此时检验代码要么Controller类调用Service类,一步步到selectById方法,要么生成单元测试

执行测试:

java 复制代码
@SpringBootTest
class UserInfoMapperTest {
    // 注入代理对象
    @Autowired
    private UserInfoMapper userInfoMapper;
    @BeforeEach
    void setUp() {
        System.out.println("在测试之前执行");
    }

    @AfterEach
    void tearDown() {
        System.out.println("在测试之后执行");
    }

    @Test
    void selectByPass() {
        UserInfo userInfo = userInfoMapper.selectByPass();
        System.out.println(userInfo);
    }
}

3>:insert:一个参数的基本查找信息

方法一:直接传递参数

代码:

java 复制代码
    @Select("select * from user_info where `password` = #{pass}")
    UserInfo selectByPassAndOneVar(String pass);

测试代码:

java 复制代码
    @Test
    void selectByIdAndOneVar() {
        System.out.println(userInfoMapper.selectByPassAndOneVar("lisi"));
    }

方法二:设置别名

代码:

java 复制代码
    @Select("select * from user_info where `password` = #{p}")
    UserInfo selectByPassAndOneVar(@Param("p") String pass);

4>:insert:多个参数的基本查找信息

方法一:直接传递参数

代码:

java 复制代码
    @Select("select * from user_info where id = #{id}  or `password` = #{pass}  ")
    List<UserInfo> selectSomeVar(Integer id,String pass);

测试代码:

java 复制代码
    @Test
    void selectSomeVar() {
        List<UserInfo> userInfoList = userInfoMapper.selectSomeVar(1, "zhangsan");
        userInfoList.forEach(System.out::println);
    }

方法二:传递对象

mybatis本质就是映射,只要把该对象传递,他会寻找名字相同的变量进行自动匹配

代码:

java 复制代码
    @Select("select * from user_info where id = #{id}  or `password` = #{password}  ")
    List<UserInfo> selectSomeVar(UserInfo userInfo);

测试代码:

java 复制代码
    @Test
    void selectSomeVar() {
        UserInfo userInfo = new UserInfo();
        userInfo.setId(3);
        userInfo.setPassword("zhangsan");
        List<UserInfo> userInfoList = userInfoMapper.selectSomeVar(userInfo);
        userInfoList.forEach(System.out::println);
    }

5>:处理值不正确情况

通过观察上述情况,发现每一次查找在mysql的返回值中,delete_flag、create_time与update_time字段明明有值,但是打印的值却是空的

**原因:**还是那句话,mybatis本质就是映射

当我们执行并调用对应的方法,实际上是代理对象 先从方法中读取并匹配参数 ,接着去对应的数据库查找并将返回的值按照名字相同进行赋值,此处就是因为对象名字与字段名字不匹配导致赋值失败
**解决办法一:**主动修改对象属性名为小写蛇形(可以,但不符合java命名规范)
**解决办法二:**使用注解Results进行重命名

测试代码:

java 复制代码
    @Test
    void selectSomeVar() {
        UserInfo userInfo = new UserInfo();
        userInfo.setId(3);
        userInfo.setPassword("zhangsan");
        List<UserInfo> userInfoList = userInfoMapper.selectSomeVar(userInfo);
        userInfoList.forEach(System.out::println);
    }

解决办法三 :加上配置,mybaits此时会将sql中的字段去除下划线+小驼峰重新拼接,此时就与属性名相同

java 复制代码
mybatis:
  configuration:  
    map-underscore-to-camel-case: true #配置驼峰⾃动转换

将Results注解屏蔽后执行结果:

6>: insert**:一行数据**

**方法一:**直接在方法参数传入值
**方法二:**传递对象,利用映射规则把属性值映射在sql语句中

代码:

java 复制代码
    @Insert("insert into user_info(username,`password`,age,gender,phone) " +
            "values (#{username},#{password},#{age},#{gender},#{phone})")
    Integer InsertRowValues(UserInfo userInfo);

测试代码:

java 复制代码
    @Test
    void insertRowValues() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("赵六");
        userInfo.setPassword("zhaoliu");
        userInfo.setAge(22);
        userInfo.setGender(0);
        userInfo.setPhone("11223344");
        int result = userInfoMapper.InsertRowValues(userInfo);
        System.out.println("影响行数>:"+result);
    }

**方法三:**使用parm修改对象名

需要注意点:若是普通成员重命名依然可以传递:若是对象进行重命名,会被认为是个普通变量,此时 新名字+ '.' +属性才可以访问内部

代码:

java 复制代码
    @Insert("insert into user_info(username,`password`,age,gender,phone) " +
            "values (#{U.username},#{U.password},#{U.age},#{U.gender},#{U.phone})")
    Integer InsertRowValues(@Param("U") UserInfo userInfo);

7>:insert:拿到新添加的数据

当我们新增加一行数据后,可能需要拿到这行数据某个值进行各种crud等操作,如何拿到??

方法一:方法返回值变为对象

此时会按照映射规则把字段赋值给属性(名称不一样注意加注解/配置)

方法二:使用注解@Options(useGeneratedKeys = true, keyProperty = "id")

useGeneratedKeys: 表示"开启'使用数据库生成的主键'"

**keyProperty:**把自增主键赋值给实体类的哪个属性

代码:

java 复制代码
    @Insert("insert into user_info(username,`password`,age,gender,phone) " +
            "values (#{U.username},#{U.password},#{U.age},#{U.gender},#{U.phone})")
    @Options(useGeneratedKeys = true,keyProperty = "id")
    Integer InsertRowValues(@Param("U") UserInfo userInfo);

测试代码:

java 复制代码
    @Test
    void insertRowValues() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("赵六");
        userInfo.setPassword("zhaoliu");
        userInfo.setAge(22);
        userInfo.setGender(0);
        userInfo.setPhone("11223344");
        int result = userInfoMapper.InsertRowValues(userInfo);
        System.out.println("对象内的值>:"+userInfo.getId());
        System.out.println("影响行数>:"+result);
    }

可以看到,这个option自动回填主键的值,并且在select不生效

8.delete:删除一行数据

delete只能返回void或Integer

代码:

java 复制代码
    @Delete("delete from user_info where id = #{id}")
    Integer DeleteById(Integer id);

测试代码:

java 复制代码
    @Test
    void deleteById() {
        Integer digital = userInfoMapper.DeleteById(6);
        System.out.println(digital);
    }

9>:update:更新一条数据

代码:

java 复制代码
    @Update("update user_info set age = 43 where username = 'lisi'")
    Integer UpdateByUser();

测试代码:

java 复制代码
    @Test
    void updateByUser() {
        Integer digital = userInfoMapper.UpdateByUser();
        System.out.println(digital);
    }

3.xml数据库操作

1>:配置与创建

通过配置xml文件进行操作数据库,思路为:

稍微提取一下:项目加载提取配置 --->根据namepace等配置statement对象放入缓存--->代理对象根据全限定方法名称查找对象并执行sql语句--->进行数据库交互 --->结果处理员与返回

可以看到我们需要: xml配置、数据库配置、xml与接口的关联、结果处理

开始配置:

将以下文件配置导入UserInfoXmlMapper文件中,重新创建并将对应接口的全限定名称加入namespace中

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.example.demo.Mapper.UserInfoXmlMapper"> 
<!--添加自己的配置-->

</mapper>

xml里面只需要注意格式,其他内容完全与注解操作一样

2>:select:查询一条数据

第一个:普通查找

代码:

XML 复制代码
    <select id="selectById" resultType="com.example.demo.Entity.UserInfo">
<!--        id为方法名,返回值只有select存在,且类型必须加上全限定类名-->
        select * from user_info where `password` = 'lisi'
    </select>
java 复制代码
    UserInfo selectById();

测试代码:

java 复制代码
    @Test
    void selectById() {
        System.out.println(userInfoXmlMapper.selectById());
    }

第二个:重命名参数查找

代码:

XML 复制代码
    <select id="selectByPassAndOneVar" resultType="com.example.demo.Entity.UserInfo">
        select * from user_info where `password` = #{p}
    </select>
java 复制代码
    UserInfo selectByPassAndOneVar(@Param("p") String pass);

测试代码:

java 复制代码
    @Test
    void selectByPassAndOneVar() {
        System.out.println(userInfoXmlMapper.selectByPassAndOneVar("lisi"));
    }

第三个:处理为空情况

在上面介绍我们可以配置mybatis自动驼峰转换用as起别名 ,也可以用Results注解进行映射,在xml中则使用

代码:

XML 复制代码
<!--    模仿注解Results-->
<!--    id:给当前标签起个名字   type:返回的实体的全限定类名-->
    <resultMap id="XmlResults" type="com.example.demo.Entity.UserInfo">
<!--        里面与Result一样-->
        <result column="delete_flag" property="deleteFlag"></result>
        <result column="create_time" property="createTime"></result>
        <result column="update_time" property="updateTime"></result>
    </resultMap>
<!--    使用了resultMap标签后,select中不允许resultType-->
    <select id="selectSomeVar" resultMap="XmlResults">
        select * from user_info where id = #{id}  or `password` = #{password}
    </select>
java 复制代码
    List<UserInfo> selectSomeVar(UserInfo userInfo);

测试代码:

java 复制代码
    @Test
    void selectSomeVar() {
        UserInfo userInfo = new UserInfo();
        userInfo.setId(1);
        userInfo.setPassword("zhaoliu");
        List<UserInfo> userInfoList = userInfoXmlMapper.selectSomeVar(userInfo);
        userInfoList.forEach(System.out::println);

    }

3>:insert:添加一条数据

第一个:普通添加

注意:insert update update默认返回影响行数,标签不写返回类型,否则会报不支持返回值的错

代码:

XML 复制代码
    <insert id="InsertRowValues" >
        insert into user_info(username,`password`,age,gender,phone)
        values (#{U.username},#{U.password},#{U.age},#{U.gender},#{U.phone});
    </insert>
java 复制代码
    Integer InsertRowValues(@Param("U") UserInfo userInfo);

测试代码:

java 复制代码
    @Test
    void insertRowValues() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("赵六");
        userInfo.setPassword("zhaoliu");
        userInfo.setAge(22);
        userInfo.setGender(0);
        userInfo.setPhone("11223344");
        Integer integer = userInfoXmlMapper.InsertRowValues(userInfo);
        System.out.println("影响行数>:"+integer);
    }

第二个:拿到自增主键

代码:

XML 复制代码
    <insert id="InsertRowValues" useGeneratedKeys="true" keyProperty="id">
        insert into user_info(username,`password`,age,gender,phone)
        values (#{U.username},#{U.password},#{U.age},#{U.gender},#{U.phone});
    </insert>
java 复制代码
    List<UserInfo> selectSomeVar(UserInfo userInfo);

测试代码:

java 复制代码
    @Test
    void insertRowValues() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("田七");
        userInfo.setPassword("tianqi");
        userInfo.setAge(16);
        userInfo.setGender(0);
        userInfo.setPhone("11334422");
        Integer integer = userInfoXmlMapper.InsertRowValues(userInfo);
        System.out.println("影响行数>:"+integer);
        System.out.println("自增主键>:"+userInfo.getId());
    }

4>:update:修改值

代码:

XML 复制代码
    <update id="UpdateByUser">
        update user_info set id = 43 where username = '田七'
    </update>
java 复制代码
   Integer UpdateByUser();

测试代码:

java 复制代码
    @Test
    void updateByUser() {
        Integer digital = userInfoXmlMapper.UpdateByUser();
        System.out.println("影响行数>:"+digital);
    }

5>:delete:删除记录

代码:

XML 复制代码
    <delete id="DeleteById">
        delete from user_info where id in (#{id1},#{id2});
    </delete>
java 复制代码
    Integer DeleteById(Integer id1,Integer id2);

测试代码:

java 复制代码
    @Test
    void deleteById() {
        Integer row = userInfoXmlMapper.DeleteById(10,43);
        System.out.println("影响行数>:"+row);
    }

三.小总结

1.重点理解mybatis的映射规则:把「数据库表的列」和「Java 实体类的属性」做匹配绑定,前提是名字匹配

2.不匹配可通过sql语句重命名、Results+Result(xml用resultMap+result)注解进行匹配与加配置项解决

3. 在cud中,对于xml而言是硬编码 ,无返回类型,有且唯一是影响行数 ;在注解中是软编码 ,根据方法返回类型自动进行类型转换适应匹配

相关推荐
モンキー・D・小菜鸡儿2 小时前
Android 自定义浮动线条视图实现:动态视觉效果的艺术
android·java
予枫的编程笔记2 小时前
【Java进阶2】Java常用消息中间件深度解析:特性、架构与适用场景
java·kafka·rabbitmq·rocketmq·activemq
一路向北North2 小时前
java 下载文件中文名乱码
java·开发语言·python
2401_837088502 小时前
Spring Boot 常用注解详解:@Slf4j、@RequestMapping、@Autowired/@Resource 对比
java·spring boot·后端
IndulgeCui2 小时前
Kingbase-KEMCC配置集群监控纳管ES以及外部备份使用对象存储
数据库
步步为营DotNet2 小时前
深度解析C# 11 的Required成员:编译期验证逻辑与稳健编程实践
java·服务器·c#
沛沛老爹2 小时前
2025年AI冲击下的Java Web开发现状
java·开发语言·人工智能·程序人生·职场和发展·年度总结
秋深枫叶红2 小时前
嵌入式第四十三篇——数据库
linux·数据库·学习·oracle
木辰風2 小时前
EasyExcel根据动态字段,进行导出excel文件
java·前端·excel