Java EE 进阶:8.MyBatis 操作数据库(入门)(第二弹)

目录

[3.MyBatis 的基础操作](#3.MyBatis 的基础操作)

[3.1 打印日志](#3.1 打印日志)

[3.2 参数传递](#3.2 参数传递)

传递一个参数

传递多个参数

​编辑

@Param:参数绑定/参数重命名

[3.3 增(Insert)](#3.3 增(Insert))

返回主键

小结

[3.4 删(Delete)](#3.4 删(Delete))

[3.5 改(Update)](#3.5 改(Update))

[3.6 查(Select)](#3.6 查(Select))

原因分析:

解决办法:

[3.6.1 起别名](#3.6.1 起别名)

[3.6.2 结果映射](#3.6.2 结果映射)

[3.6.3 开启驼峰命名(推荐)](#3.6.3 开启驼峰命名(推荐))


书接上文:Java EE 进阶:8.MyBatis 操作数据库(入门)(第一弹)~~

3.MyBatis 的基础操作

注:下面增删改查的部分建议先看 查 的部分!!

因为是从查往下引的~~
上面我们学习了Mybatis的查询操作, 接下来我们学习MyBatis的增, 删, 改操作

在学习这些操作之前, 我们先来学习MyBatis日志打印

3.1 打印日志

在Mybatis当中我们可以借助日志, 查看到sql语句的执行、执行传递的参数以及执行结果

在配置文件中进行配置即可

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

上面内容直接复制粘贴到 application.yml 即可,还是那句话,不用记不用背,直接放在一个能找到的地方就行了,比如放在码云、博客里,只需要知道这是个什么东西,会做选择题就行了~~

如果是application.properties, 配置内容如下:

java 复制代码
#指定mybatis输出日志的位置,输出控制台
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

注意: 后续配置项, 默认只提供一种, 请自行进行配置项转换.

运行程序后发现日志里多了这些内容👇

重新运行程序, 可以看到SQL执行内容, 以及传递参数和执行结果

①: 查询语句

②: 传递参数及类型

③: SQL执行结果

3.2 参数传递

传递一个参数

我们有时候需要查询某一个用户~~

需求: 查找 id=2 的用户,对应的SQL就是: select * from user_info where id=2👇

之前是多条数据,我们使用 List 来接收👇

java 复制代码
    @Select("select * from user_info")
    List<UserInfo> selectAll();

现在是单条数据,我们使用对象来接收👇

java 复制代码
    @Select("select * from user_info where id = 2")
    UserInfo selectAllById();

然后我们写测试用例👇依旧右键→测试,这次我们选第二个

直接选择更新即可👇

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

运行一下👇我们发现响应的数据没有问题👇

但是这样的话, 只能查找 id=4 的数据, 所以 SQL 语句中的 id 值不能写成固定数值,需要变为动态的数值

解决方案:在queryById方法中添加一个参数(id),将方法中的参数,传给SQL语句

使用 #{} 的方式获取方法中的参数

java 复制代码
    @Select("select * from user_info where id = #{id}")
    UserInfo selectAllById(Integer id);

然后测试用例我们取 id 为 1👇

java 复制代码
    @Test
    void selectAllById() {
        System.out.println(userInfoMapper.selectAllById(1));
    }

我们运行后发现确实拿到了 id=1 的数据👇

那现在有的同学又来疑问了:那这不还是写死了吗??

大家想想这是什么??这是测试用例,实际过程中,我们测试代码是不走的,我们测试用例测的是参数有没有给它传过去,这个测试用例的代码并不是我们真实要执行的代码,我们真实要执行的代码是通过参数传过来的

java 复制代码
    @RequestMapping("/getUserInfoById")
    public UserInfo getUserInfoById(Integer id){
        return userService.getUserInfoById(id);
    }
java 复制代码
    public UserInfo getUserInfoById(Integer id) {
        return userInfoMapper.selectAllById(id);
    }

启动启动类,在网址上的查询字符串部分,设为 id=1,就可以查到对应的数据库信息了👇

同样,id=2,id=3 的数据也可以得到👇

也就是说这个参数是前端给我们传的,我们当前只是为了方便从测试,在测试用例中是写死的,但是并不代表我们在这里是写死的,它是接收的参数,只不过看谁调用这个方法,谁给我传这个参数而已,这个参数在真实的开发中是前端给我们传,前端传到 Controller,Controller 传给 Service,Service 再传给 Mapper,Mapper 又把这个值赋上去~~


刚刚的代码大家应该也注意到了,类型从 List 改成了 UserInfo 这个对象,那什么时候使用 List?什么时候使用对象?

我们来再创建一个新的,看看刚刚用对象接收的,现在用 List 接收行不行👇

java 复制代码
    @Select("select * from user_info where id = #{id}")
    List<UserInfo> selectAllById2(Integer id);
java 复制代码
    @Test
    void selectAllById2() {
        System.out.println(userInfoMapper.selectAllById2(4));
    }

运行这个测试用例,我们观察一下二者的差异👇

我们发现也是可以执行成功的,只不过是带了个中括号,表示这是一个 List

那么我们能不能把原本要返回 List(包含多行数据) 的给改成 对象呢??来尝试一下👇

java 复制代码
    @Select("select * from user_info")
    UserInfo selectAll2();
java 复制代码
    @Test
    void testSelectAll2() {
        System.out.println(userInfoMapper.selectAll2());
    }

我们再来运行测试用例👇

我们从下往上看,发现错误日志写的很明确:太多结果了,期望的是一个结果或者是 null,但是却发现了 4个

也就是说这个 SQL 语句执行出来的结果是 4个,但是只用了一个对象去接收,我不知道这四个数据我到底挑哪个赋值给它,所以报错了,对象太多了~~

综上得出结论:

(1)使用对象接收:结果只能是一个 或者 null

(2)使用 List 接收: 无所谓

所以:

如果返回结果为 0~1 条数据,使用 对象 或者 List 都可以

如果返回结果 >1 条,必须使用 List


传递多个参数

如果说接下来我想执行这个 SQL 语句👇,而这句 SQL 的结果不一定是多条也不一定是一条,因为我们的 username 和 password 并没有把它设置为唯一主键

因为可能存在多条,那么对于这种情况我们就使用 List 来接收👇

java 复制代码
    //对于SQL语句,单引号和双引号都是可以执行成功的,为方便表示我们改为单引号👇
    @Select("select * from user_info where username = 'zhangsan' and password = 'zhangsan'")
    List<UserInfo> selectByNameAndPassword(String username,String password);

模仿传递一个参数的格式,我们做出如下改动👇

java 复制代码
    @Select("select * from user_info where username = #{username} and password = #{password}")
    List<UserInfo> selectByNameAndPassword(String username,String password);

依旧右键→测试→OK 来生成测试方法

打印👇

java 复制代码
    @Test
    void selectByNameAndPassword() {
        userInfoMapper.selectByNameAndPassword("zhangsan","zhangsan")
                .stream().forEach(x-> System.out.println(x));
    }

观察结果👇

我们发现结果跟数据返回的 id 为 2 的是一样的👇

那现在又有问题了,这个参数的名称是不是有序的,能不能换一下??

为了区分交换前后效果,我们先把相同的数据内容做出一些修改,把密码改为 zhangsan123👇

那么修改前👇

java 复制代码
    @Select("select * from user_info where username = #{username} and password = #{password}")
    List<UserInfo> selectByNameAndPassword(String username,String password);
java 复制代码
    @Test
    void selectByNameAndPassword() {
        userInfoMapper.selectByNameAndPassword("zhangsan","zhangsan123")
                .stream().forEach(x-> System.out.println(x));
    }

修改后👇

java 复制代码
    @Select("select * from user_info where username = #{username} and password = #{password}")
    List<UserInfo> selectByNameAndPassword(String password,String username);
java 复制代码
    @Test
    void selectByNameAndPassword() {
        userInfoMapper.selectByNameAndPassword("zhangsan123","zhangsan")
                .stream().forEach(x-> System.out.println(x));
    }

通过观察发现:顺序并不影响结果,只要参数名称能一一对应上就可以了~~

那么现在又有一个问题了:既然上面只有一个参数,那么我就把 id 改为 id1,它能不能找到呢??👇

java 复制代码
    @Select("select * from user_info where id = #{id1}")
    List<UserInfo> selectAllById2(Integer id);
java 复制代码
    @Test
    void selectAllById2() {
        System.out.println(userInfoMapper.selectAllById2(4));
    }

我们发现是可以找到的👇

类似的,改成 aa 也可以,结果如上,就不演示了,这说明无论改成什么名字都可以识别出来,也就是"只有一个,没得选"的感觉

那要是参数不一样,把名称也改掉呢??我们下面把 username 改为 aa,password 改为 bb 试试看👇

java 复制代码
    @Select("select * from user_info where username = #{aa} and password = #{bb}")
    List<UserInfo> selectByNameAndPassword(String password,String username);
java 复制代码
    @Test
    void selectByNameAndPassword() {
        userInfoMapper.selectByNameAndPassword("zhangsan123","zhangsan")
                .stream().forEach(x-> System.out.println(x));
    }

此时就报错了👇

错误日志写的很清楚:参数绑定异常,aa 没有找到,可用的参数是 password、param1、username、param2(param1 和 param2 是按着顺序根据 password 和 username 生成的)~~

结论:

参数只有一个的时候,没得选,名称随意

参数≥2个的时候,名称就需要对应上,否则找不到

接下来再来尝试,既然 param1 和 param2 是可用参数,那我改成这俩试试呗,我也不按顺序来,我先写 param2(跟随 username 生成的),再写 param1(跟随 password 生成的)👇

java 复制代码
    @Select("select * from user_info where username = #{param2} and password = #{param1}")
    List<UserInfo> selectByNameAndPassword(String password,String username);
java 复制代码
    @Test
    void selectByNameAndPassword() {
        userInfoMapper.selectByNameAndPassword("zhangsan123","zhangsan")
                .stream().forEach(x-> System.out.println(x));
    }

发现是能够使用的👇

所以我们能使用的参数可以是 param1 和 param2,但是此种方式不建议使用:

1.可读性差

2.易出错,比如我现在增加一个参数👇

java 复制代码
    @Select("select * from user_info where username = #{param2} and password = #{param1}")
    List<UserInfo> selectByNameAndPassword(Integer age,String password,String username);
java 复制代码
    @Test
    void selectByNameAndPassword() {
        userInfoMapper.selectByNameAndPassword(1,"zhangsan123","zhangsan")
                .stream().forEach(x-> System.out.println(x));
    }

此时我们发现参数对应就出错了👇

因为加上 Integer age 之后,age 是 param1,password 是 param2,username 是 param3 了,所以我们应该改成这样👇

java 复制代码
    @Select("select * from user_info where username = #{param3} and password = #{param2}")
    List<UserInfo> selectByNameAndPassword(Integer age,String password,String username);

但这对于我们来说是非常麻烦且容易出错的,所以就不建议大家使用 param,大家知道就行了~~

@Param:参数绑定/参数重命名

我们之前学习 SpringMVC 的时候学过参数重命名,使用的注解是 @RequestParam,也就是参数的绑定,同样的,我们的 MyBatis 也提供了这个功能,上面提到了 MyBatis 会根据我们的参数来帮我们生成变量,比如参数名称是 password,它会帮我们生成 password、param1,然后 username,它会帮我们生成 username、param2,但是我觉得 password 这个名字不好听,我想改个名,我就觉得 userName 好听,这时候咋办??使用 @Param 注解~~

java 复制代码
    @Select("select * from user_info where username = #{userName} and password = #{password}")
    List<UserInfo> selectByNameAndPassword(@Param("password")String password,@Param("userName")String username);
java 复制代码
    @Test
    void selectByNameAndPassword() {
        userInfoMapper.selectByNameAndPassword("zhangsan123","zhangsan")
                .stream().forEach(x-> System.out.println(x));
    }

我们发现它是能够正常获取的👇

那么此时如果把注解去掉,就会找不到 userName 而报错了👇

java 复制代码
    @Select("select * from user_info where username = #{userName} and password = #{password}")
    List<UserInfo> selectByNameAndPassword(@Param("password")String password,String username);

3.3 增(Insert)

先写 SQL 语句👇

我们之前学习 Spring 的时候,接收一个参数→接收两个参数→接收多个参数→接收对象,那么类似的,我们这次使用对象接收👇

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

答疑:参数可以搞到配置文件吗??

不可以哦,配置文件一般不会做这些事情,配置文件虽然是可改变的,但是也不能这么改变,但是 SQL 是可以考虑的~~


生成测试用例👇

java 复制代码
    @Test
    void insertUser() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("username1");
        userInfo.setPassword("password1");
        userInfo.setAge(2);
        Integer result=userInfoMapper.insertUser(userInfo);
        System.out.println("影响行数:"+result);
    }

运行成功👇

我们发现确实也插入成功了👇

返回主键

Insert 语句默认返回的是 受影响的行数

但有些情况下, 数据插入之后, 还需要有后续的关联操作, 需要获取到新插入数据的 id

比如订单系统

当我们下完订单之后, 需要通知物流系统, 库存系统, 结算系统等, 这时候就需要拿到订单 ID

如果想要拿到自增 id, 需要在 Mapper 接口的方法上添加一个 Options 的注解(默认是 false,这里设置成 true)

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

• useGeneratedKeys:这会令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法来取出由数据库内部生成的主键(比如:像 MySQL 和 SQL Server 这样的关系型数据库管理系统的自动递增字段),默认值:false.

• keyProperty:指定能够唯一识别对象的属性,MyBatis 会使用 getGeneratedKeys 的返回值或 insert 语句的 selectKey 子元素设置它的值,默认值:未设置(unset)

java 复制代码
    @Test
    void insertUser() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("username3");
        userInfo.setPassword("password3");
        userInfo.setAge(4);
        Integer result=userInfoMapper.insertUser(userInfo);
        System.out.println("影响行数:"+result+",id:"+userInfo.getId());
    }

运行结果:

注意: 设置 useGeneratedKeys=true 之后, 方法返回值依然是受影响的行数, 自增 id 会设置在上述 keyProperty 指定的属性中.

我们再来试试参数绑定 @Param,只是加上 @Param,而且重命名的还是一样的名字👇

java 复制代码
    @Options(useGeneratedKeys = true,keyProperty = "id")
    @Insert("insert into user_info (username,`password`,age) values (#{username},#{password},#{age})")
    Integer insertUser2(@Param("userInfo")UserInfo userInfo);
java 复制代码
    @Test
    void insertUser2() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("username3");
        userInfo.setPassword("password3");
        userInfo.setAge(4);
        Integer result=userInfoMapper.insertUser2(userInfo);
        System.out.println("影响行数:"+result+",id:"+userInfo.getId());
    }

我们发现还是报错了👇

报错信息说:username 找不着,能用的参数只有 userInfo 和 param1,param1 我们知道,第一个参数就是 param1,而 userInfo 就是注解 @Param(userInfo) 里面的,所以我们要想使用的话就必须写成👇

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

现在又出现一个问题,这一行太长了,我们需要换行,但是注解怎么换行??

注解里是一个字符串,所以我们用 + 的方式来拼接换行即可👇

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

1.单元测试

@SpringBootTest:当你需要 Spring 的运行环境时需要加,如果不需要可以不加

@Test:表示这是一个测试方法,它可以自己运行

@BeforeEach:在每一个测试方法执行前执行

@AfterEach:在每一个测试方法执行后执行

如果我们想要拿到运行环境的话,第一个是通过 ApplicationContext 直接注入进来👇

java 复制代码
@Autowired
private ApplicationContext context;

注入进来之后得到的就是我们的启动类运行出来的结果

再或者我们也可以直接去拿👇

java 复制代码
@Autowired
private UserInfoMapper userInfoMapper;

2.打印日志

3.MyBatis 的基本操作

1)参数传递:#{参数名称}

①传递单个参数:名称可以不一致,但是建议保持一致

②传递多个参数:MyBatis 会根据方法的定义,根据参数名称,生成参数(建议使用这个参数名),还会按顺序生成参数 param1、param2......

③传递对象:MyBatis 会根据 Java 属性来生成参数,直接使用属性名称就行👇

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

④参数绑定 @Param:也可以指定生成的参数名称

之前如果是根据对象的话,咱们直接使用属性名称就可以了,但是如果你使用了 @Param 这个注解的话,使用对象的时候,参数的名称对应需要加上一个 点( . )👇

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

2)数据库操作

①查询:用 @Select

存在问题:当字段名和属性名对应不上时(这个还没讲,下面 3.6 查 部分会讲)

Ⅰ起别名:不一样就用 SQL 设置成一样的

Ⅱ结果映射:用 @Results 指定映射关系

Ⅲ驼峰自动转换:配置文件中设置

②新增:用 @Insert

@Options:可以获得它一个自增的 ID

下面 3.6 查 部分还涉及到:

@Results

@Result

@ResultMap

3.4 删(Delete)

除了查询,增、改、删 返回的数据结果都是影响的行数,当然这个数据你可以不要,不要的话就定义成 void 就行了

java 复制代码
    //删:根据 id 进行删除,接受类型也可以是 Long、Int
    @Delete("delete from user_info where id=#{id}")
    Integer deleteUser(Integer id);
java 复制代码
    @Test
    void deleteUser() {
        userInfoMapper.deleteUser(9);//删除id为9的数据
    }

删之前👇

运行程序👇

注意:日志显示删除成功不一定是真的成功,还是要看数据库真实数据,此时就完成了删除👇

3.5 改(Update)

java 复制代码
    //更新:注意给值的时候是属性名称,比如:deleteFlag
    @Update("update user_info set delete_flag=#{deleteFlag},phone=#{phone} where id=#{id}")
    Integer updateUser(UserInfo userInfo);

我们对 id 为 8 的数据进行更新👇

java 复制代码
    @Test
    void updateUser() {
        UserInfo userInfo=new UserInfo();
        userInfo.setId(8);
        userInfo.setDeleteFlag(1);
        userInfo.setPhone("12233356666");
        userInfoMapper.updateUser(userInfo);
    }

更新前👇

运行成功👇

数据库也完成了更新👇

那如果我们不给它设置 id 呢??

java 复制代码
    @Test
    void updateUser() {
        UserInfo userInfo=new UserInfo();
//        userInfo.setId(8);
        userInfo.setDeleteFlag(1);
        userInfo.setPhone("12233356666");
        userInfoMapper.updateUser(userInfo);
    }

我们发现也是运行成功了的👇id 值为 null,影响行数为 0

这也证实了,运行成功了,日志不报错,并不能代表成功~~

日志没有错误,不代表 运行结果正确

日志显示运行结果正确,不代表 数据操作成功,要看数据库数据

3.6 查(Select)

解决问题:当字段名和属性名对应不上时👇

java 复制代码
    @Select("select * from user_info")
    List<UserInfo> selectAll();
java 复制代码
    @Test
    void selectAll() {
        System.out.println(userInfoMapper.selectAll());
    }

我们在上面查询时发现, 有几个字段是没有赋值的, 只有Java对象属性和数据库字段一模一样时, 才会进行赋值

从运行结果上可以看到, 我们SQL语句中, 查询了delete_flag, create_time, update_time, 但是这几个属性却没有赋值.

原因分析:

当自动映射查询结果时,MyBatis 会获取结果中返回的列名并在 Java 类中查找相同名字的属性(忽略大小写)。 这意味着如果发现了 ID 列和 id 属性,MyBatis 会将列 ID 的值赋给 id 属性

解决办法:

就是告诉 MyBatis 两两之间映射的关系~~

  1. 起别名

  2. 结果映射

  3. 开启驼峰命名

3.6.1 起别名

在SQL语句中,给列名起别名,保持别名和实体类属性名一样

sql 复制代码
select id,username,`password`,age,gender,phone,
delete_flag as deleteFlag,create_time as createTime,update_time as updateTime
from user_info

运行后发现就好了👇

将上述 SQL 代码 CV 到原代码上👇

java 复制代码
//    @Select("select * from user_info")
    @Select("select id,username,`password`,age,gender,phone," +
            "delete_flag as deleteFlag,create_time as createTime,update_time as updateTime" +
            " from user_info")
    List<UserInfo> selectAll();
java 复制代码
    @Test
    void selectAll() {
        System.out.println(userInfoMapper.selectAll());
    }

此时我们就能发现有值了👇

3.6.2 结果映射

上面的方式就是交给 SQL 处理了,太麻烦了,我们接下来使用注解 @Results 来解决,源码👇我们会发现这个是我们从没接触过的数组类型为注解 Result

java 复制代码
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Results {

  String id() default "";

  Result[] value() default {};
}

点开查看注解 Result 的源码👇

java 复制代码
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Repeatable(Results.class)
public @interface Result {

  boolean id() default false;

  String column() default "";

  String property() default "";

  Class<?> javaType() default void.class;

  JdbcType jdbcType() default JdbcType.UNDEFINED;

  Class<? extends TypeHandler> typeHandler() default UnknownTypeHandler.class;

  One one() default @One;

  Many many() default @Many;
}

column 猜也猜出来是数据库相关的,因为下面是 JDBC 的 type,也就是说类型也可以做一些转换的,知道格式之后我们下面来使用👇

java 复制代码
    @Results({
            @Result(column = "delete_flag",property = "deleteFlag"),//列名:delete_flag,属性名:deleteFlag
            @Result(column = "create_time",property = "createTime"),
            @Result(column = "update_time",property = "updateTime"),
    })
    @Select("select * from user_info")
    List<UserInfo> selectAll();
java 复制代码
    @Test
    void selectAll() {
        System.out.println(userInfoMapper.selectAll());
    }

此时运行结果就映射上了👇

问题又来了,我在上面写一个,那我在下面的 @select 还得再写一个,怪麻烦的,而且要是单纯复制粘贴还好,但要是修改了咋办?那不是意味着我全部都要重新再复制粘贴一遍??

这就太麻烦了,所以我们希望把它给提取出来,能直接给其他地方用~~

如果其他SQL, 也希望可以复用这个映射关系, 可以给这个Results 定义一个名称👇(比如定义为 BaseMap)

java 复制代码
    @Results(id="BaseMap",value={
            @Result(column = "delete_flag",property = "deleteFlag"),//列名:delete_flag,属性名:deleteFlag
            @Result(column = "create_time",property = "createTime"),
            @Result(column = "update_time",property = "updateTime"),
    })
    @Select("select * from user_info")
    List<UserInfo> selectAll();

使用 id 属性给该 Results 定义别名, 使用 @ResultMap 注解来复用其他定义的 ResultMap

先来看一下没加上面注解的另一个代码👇

java 复制代码
    @Select("select * from user_info where id = #{id}")
    UserInfo selectAllById(Integer id);
java 复制代码
    @Test
    void selectAllById() {
        System.out.println(userInfoMapper.selectAllById(1));
    }

发现此时是获取不到的👇

下面我们加上这个注解再次尝试👇

java 复制代码
    @ResultMap(value="BaseMap")
    @Select("select * from user_info where id = #{id}")
    UserInfo selectAllById(Integer id);
java 复制代码
    @Test
    void selectAllById() {
        System.out.println(userInfoMapper.selectAllById(1));
    }

发现此时就能够获取到了👇说明我们就可以重复利用了

而且我们还可以发现,上述的类型是对象,而上上面的是 类型是 List,说明这都是不影响映射的~~

3.6.3 开启驼峰命名(推荐)

我们程序员就是懒,现在连这个转换关系也不想写了,无非就是把蛇形的转换成驼峰的还非得我一个个写??这是不是有规律可循呢??我们是不是可以放在配置里呢??

我们的 MyBatis 也支持自动转换,把这个放在了 配置项 里,只要你配置,它就能自动转

通常数据库列使用蛇形命名法进行命名(下划线分割各个单词), 而 Java 属性一般遵循驼峰命名法约定.

为了在这两种命名方式之间启用自动映射,需要将 mapUnderscoreToCamelCase 设置为 true。

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

驼峰命名规则: abc_xyz => abcXyz

• 表中字段名:abc_xyz

• 类中属性名:abcXyz

Java 代码不做任何处理

我们直接把上述代码放到配置文件 .yml 文件下

java 复制代码
spring:
  application:
    name: mybatis-demo

# 数据库连接配置
  datasource:
#    url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false
    url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true
    username: root
#    password: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
  configuration:  # 配置打印 MyBatis日志
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

    map-underscore-to-camel-case: true #配置驼峰自动转换

原代码不做改变👇

java 复制代码
    @Select("select * from user_info")
    List<UserInfo> selectAll();
java 复制代码
    @Test
    void selectAll() {
        System.out.println(userInfoMapper.selectAll());
    }

运行代码:

字段全部进行正确赋值.

这就是之前为什么说要一一对应起来的原因,能够方便把蛇形的转成驼峰~~
答疑:

Q1:MVC 的 service 是干什么的(忘了)

MVC:model、view、controller

三层架构:表现层、业务逻辑层、数据层

Controller、Service、Dao

Q2:它怎么知道用哪个数据库和哪张表??

果然是忘得快~~

1.添加 MyBatis 和 MySQL 的依赖

2.配置数据库信息:在配置信息中都写了地址和名称......👇

java 复制代码
    url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true
相关推荐
CQU_JIAKE3 小时前
11.7[高体】
java·后端·spring
wafrdggh3 小时前
2026电商快递批量查询怎么用?固乔助手模板设置评测
大数据·数据库·小程序
一个天蝎座 白勺 程序猿3 小时前
KingbaseES数据库归档重做日志文件管理:从配置到运维的实战指南
运维·数据库·oracle·kingbasees·金仓数据库
apcipot_rain4 小时前
C++转Java日记(04)
java·开发语言·c++
特立独行的猫A4 小时前
我给女儿写了个打字练习:一边敲键盘,一边把小学英语单词记牢
java·后端·python
憧憬成为java架构高手的小白6 小时前
LangGraph4j 实战(下)
java
天诰6 小时前
SA-K-11 检索会消失吗与四个未解问题
java·服务器·人工智能·python·机器学习·ai编程
龙腾AI白云7 小时前
仿真到现实(Sim-to-Real)迁移:跨越仿真与现实鸿沟
数据库·机器学习·plotly·知识图谱·tornado
freejackman9 小时前
【实战二】字段级血缘追踪:拆解 AST 迷局,精准穿透函数链与子查询
大数据·数据库·sql