MyBatis入门——MyBatis的基础操作(2)

目录

一、打印日志

二、参数传递

常见错误:使用对象接受

小结:

三、增(Insert)

返回主键

四、删(Delete)

五、改(Update)

六、查(Select)

1、起别名

2、结果映射

3、开启驼峰命名(推荐)


准备工作:

存在的表如下:(表名:userInfo)

代码如下:

实体类UserInfo类:

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;
}

UserController类:

java 复制代码
@RequestMapping("/user")
@RestController
public class UserController {
    @Autowired
    private UserService userService;
    @RequestMapping("/getUserAll")
    public List<UserInfo> getUserAll() {
        return userService.getUserAll();
    }
}

UserServer类:

java 复制代码
@Service
public class UserService {
    @Autowired
    private UserInfoMapper userInfoMapper;
    public List<UserInfo> getUserAll() {
        return userInfoMapper.getUserInfoAll();
    }
}

UserInfoMapper接口:

java 复制代码
@Mapper
public interface UserInfoMapper {
    @Select("select * from userinfo")
    List<UserInfo> getUserInfoAll();
    
}

一、打印日志

在MyBatis当中,我们可以借助日志,查看SQL语句的执行、执行传递的参数以及执行结果,只需在配置文件中进行配置即可,配置内容如下:

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

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

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

测试类代码如下:

java 复制代码
@SpringBootTest
class UserInfoMapperTest {
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Test
    void getUserInfoAll() {
        System.out.println(userInfoMapper.getUserInfoAll());
    }
}

运行测试类,控制台比之前多出了一些内容,如下图:


二、参数传递

需求:查找id=4的用户,对应的SQL就是:select * from userinfo where id=4;

UserInfoMapper接口代码:

java 复制代码
@Mapper
public interface UserInfoMapper {
    @Select("select * from userinfo where id=4")
    List<UserInfo> queryById();
}

测试类代码如下:

java 复制代码
@SpringBootTest
class UserInfoMapperTest {
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Test
    void queryById() {
        System.out.println(userInfoMapper.queryById());
    }
}

但代码也可以写成其他样子:传递参数的方式,代码如下:

java 复制代码
@Mapper
public interface UserInfoMapper {
    @Select("select * from userinfo")
    List<UserInfo> getUserInfoAll();
    @Select("select * from userinfo where id=#{id}")
    List<UserInfo> queryById(Integer id);
}
java 复制代码
@SpringBootTest
class UserInfoMapperTest {
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Test
    void queryById() {
        System.out.println(userInfoMapper.queryById(4));
    }
}

执行代码,结果如下:

也可以通过**@Param**,设置参数的别名,如果使用@Param设置别名,#{....}里的属性名必须和@Param设置的一样,代码如下:

java 复制代码
@Mapper
public interface UserInfoMapper {
    @Select("select * from userinfo where id=#{userid}")
    List<UserInfo> queryById2(@Param("userid") Integer id);
}

如果不设置别名,最好传递的参数要和SQL语句里的属性名一样。

常见错误:使用对象接受

现在表的数据如下:

我们查询gender=2的数据。

UserInfoMapper接口代码如下:

java 复制代码
@Mapper
public interface UserInfoMapper {
    @Select("select * from userinfo where gender=#{gender}")
    UserInfo queryById3(Integer gender);
}

测试代码如下:

java 复制代码
@SpringBootTest
class UserInfoMapperTest {
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Test
    void queryById3() {
        userInfoMapper.queryById3(2);
    }
}

运行测试代码,执行结果如下:

现在更改一下数据,gender=2的数据只有一个了,如图:

在运行测试代码,没有报错,结果如下:

小结:

对于只有一个返回结果,可以使用对象或集合接收;对于有多个返回结果,只能使用集合接收。


三、增(Insert)

SQL语句:

sql 复制代码
insert into userinfo(username, password, age, gender, phone) values("zhaoliu","zhaoliu",19,1,"18700001234");

UserInfoMapper接口代码如下:

没有使用@Param注解:

java 复制代码
@Mapper
public interface UserInfoMapper {
    @Insert("insert into userinfo(username, password, age, gender) " +
            "values(#{username}, #{password}, #{age}, #{gender})")
    Integer insert(UserInfo userInfo);
}

使用@Param注解:

java 复制代码
@Mapper
public interface UserInfoMapper {
    @Insert("insert into userinfo(username, password, age, gender) " +
            "values(#{userInfo.username}, #{userInfo.password}, #{userInfo.age}, #{userInfo.gender})")
    Integer insert(@Param("userInfo") UserInfo userInfo);
}

测试类代码如下:

java 复制代码
@SpringBootTest
class UserInfoMapperTest {
    @Test
    void insert() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("zhaoliu");
        userInfo.setPassword("123456");
        userInfo.setAge(66);
        userInfo.setGender(2);
        userInfoMapper.insert(userInfo);
    }
}

运行测试类,控制台打印内容如下:

查看userInfo表

确实多了一行,id没衔接上是因为之前我测试了一下,添加了几行数据,后面又删除了。

返回主键

想要添加主键,再加个@Options注解就好了。

UserInfoMapper接口代码:

java 复制代码
@Mapper
public interface UserInfoMapper {
    @Options(useGeneratedKeys = true, keyProperty = "id")
    @Insert("insert into userinfo(username, password, age, gender) " +
            "values(#{username}, #{password}, #{age}, #{gender})")
    Integer insert2(UserInfo userInfo);
}

注解内的属性解释:

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

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

测试类代码:

java 复制代码
@SpringBootTest
class UserInfoMapperTest {
    @Autowired
    @Test
    void insert2() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("zhaoliu");
        userInfo.setPassword("123456");
        userInfo.setAge(66);
        userInfo.setGender(2);
        Integer count = userInfoMapper.insert2(userInfo);
        System.out.println("添加数据数:" + count + "数据ID:" + userInfo.getId());
    }
}

运行测试类,运行结果如下:

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


四、删(Delete)

SQL:

sql 复制代码
delete from userinfo where id = 11

UserInfoMapper接口代码:

java 复制代码
@Mapper
public interface UserInfoMapper {
    @Delete("delete from userinfo where id = #{id}")
    Integer delete(Integer id);
}

测试类代码:

java 复制代码
@SpringBootTest
class UserInfoMapperTest {
    @Test
    void delete() {
        System.out.println(userInfoMapper.delete(11));
    }
}

运行测试类前:

运行测试类,结果如下:

可以看到,id为11的数据被删除了。


五、改(Update)

USerInfoMapper接口类代码:

java 复制代码
@Mapper
public interface UserInfoMapper {
    @Update("update userinfo set username = #{username} where id = #{id}")
    Integer upadate(String username ,Integer id);
}

测试类代码:

java 复制代码
@SpringBootTest
class UserInfoMapperTest {
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Test
    void upadate() {
        userInfoMapper.upadate("zhouba", 10);
    }
}

运行测试类前表的数据:

运行测试类,结果如下:

可以看到,修改成功了。


六、查(Select)

USerInfoMapper接口代码:

java 复制代码
@Mapper
public interface UserInfoMapper {
    @Select("select id, username, `password`, age, gender, phone, delete_flag, create_time, update_time from userinfo")
    List<UserInfo> queryAllUser();
}

测试类代码:

java 复制代码
@SpringBootTest
class UserInfoMapperTest {
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Test
    void queryAllUser() {
        System.out.println(userInfoMapper.queryAllUser());
    }
}

运行测试类代码,结果如下:

可以看到,有三个属性都是没有值的,为null原因 :数据库表的列名和实体类的属性名不一样,如图:

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

因为数据库里面的表的列名 命名规范 和 Java的属性命名规范不一样,从而导致双方给同一个对象命名的名称不同,也就不能自动给它映射了,解决办法有三种1、起别名 2、结果映射 3、开启驼峰命名

1、起别名

USerInfoMapper接口类:

java 复制代码
@Mapper
public interface UserInfoMapper {
    @Select("select id, username, `password`, age, gender, phone, " +
            "delete_flag as deleteFlag, create_time as createTime, update_time as updateTime from userinfo")
    List<UserInfo> queryAllUser2();
}

测试类:

java 复制代码
@SpringBootTest
class UserInfoMapperTest {
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Test
    void queryAllUser2() {
        System.out.println(userInfoMapper.queryAllUser2());
    }
}

运行测试类代码,结果如下:

可以看到,现在的deleteFlag、createTime、updateTime 都不是null了。

2、结果映射

使用@Results和@Result注解,USerInfoMapper类代码如下:

java 复制代码
@Mapper
public interface UserInfoMapper {
    @Results({
            @Result(column = "delete_flag", property = "deleteFlag"),
            @Result(column = "create_time", property = "createTime"),
            @Result(column = "update_time", property = "updateTime")
    })
    @Select("select id, username, `password`, age, gender, phone, delete_flag, create_time, update_time from userinfo")
    List<UserInfo> queryAllUser3();
}

测试类代码如下:

java 复制代码
@SpringBootTest
class UserInfoMapperTest {
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Test
    void queryAllUser3() {
        System.out.println(userInfoMapper.queryAllUser3());
    }
}

运行测试类代码,结果如下:

如果希望其他SQL也可以使用该映射,就给@Results注释多加个id属性,其他SQL想使用,就加@ResultMap注解使用,代码如下:

java 复制代码
@Mapper
public interface UserInfoMapper {
    @Results(id = "resultMap" , value = {
            @Result(column = "delete_flag", property = "deleteFlag"),
            @Result(column = "create_time", property = "createTime"),
            @Result(column = "update_time", property = "updateTime")
    })
    @Select("select id, username, `password`, age, gender, phone, delete_flag, create_time, update_time from userinfo")
    List<UserInfo> queryAllUser4();

    @ResultMap(value = "resultMap")
    @Select("select id, username, `password`, age, gender, phone, delete_flag, create_time, update_time from userinfo")
    List<UserInfo> queryAllUser5();
}

使用id属性给该Results定义别名,使用@ResultMap注释来复用其他定义的ResultMap。如图:

3、开启驼峰命名(推荐)

通常数据库列使用蛇形命名发进行命名(下划线分割各个单词),而Java属性一般遵循驼峰命名法约定。为了在这两种命名方式之间启用自动映射,需要将 mapUnderscoreToCamelCase 设置为true。xml文件内容如下:

XML 复制代码
mybatis:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #配置打印 MyBatis⽇志
    map-underscore-to-camel-case: true  #自动驼峰转换

驼峰命名规则 :abc_xyz => abcXyz。表中字段名 :abc_xyz。类中属性名 :abcXyz

现在重新使用下面代码测试,USerInfoMapper接口代码如下:

java 复制代码
@Mapper
public interface UserInfoMapper {
    @Select("select id, username, password, age, gender, phone, delete_flag, create_time, update_time from userinfo")
    List<UserInfo> queryAllUser();
}

测试类代码:

java 复制代码
@SpringBootTest
class UserInfoMapperTest {
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Test
    void queryAllUser() {
        System.out.println(userInfoMapper.queryAllUser());
    }
}

运行测试类代码,结果如下:

可以看到,deleteFlag、createTime、updateTime这三个属性的值不为null全都被赋值了

相关推荐
xuejianxinokok10 分钟前
新版本 python 3.14 性能到底如何?
后端·python
Ray6612 分钟前
代理模式
后端
考虑考虑13 分钟前
Jpa中的枚举类型
spring boot·后端·spring
peter52716 分钟前
LangChain4j入门使用
后端
ArabySide22 分钟前
【ASP.NET Core】分布式场景下ASP.NET Core中JWT应用教程
分布式·后端·asp.net core
hui函数1 小时前
Python全栈(基础篇)——Day06:后端内容(定义函数+调用函数+实战演示+每日一题)
后端·python
云和数据.ChenGuang1 小时前
MongoDB 连接时的**认证参数配置错误**
数据库·mongodb
用户874034852511 小时前
家政小程序源码实战:快速部署+多端适配,打造高效家政服务生态
spring boot
bcbnb1 小时前
Charles隐藏功能全攻略,10个高效技巧让你的抓包调试更专业
后端
用户4099322502121 小时前
PostgreSQL选Join策略有啥小九九?Nested Loop/Merge/Hash谁是它的菜?
后端·ai编程·trae