MyBatis操作数据库入门

什么是MyBatis

MyBatis是⼀款优秀的持久层框架,⽤于简化JDBC的开发.MyBatis是更简单完成程序和数据库交互的框架,也就是更简单的操作和读取数据库⼯具.

MyBatis入门

准备工作

创建工程

新建Spring Boot项目,并导⼊mybatis的起步依赖和mysql的驱动包.

数据准备

创建用户表,并创建对应的实体类User.

sql 复制代码
-- 创建数据库
DROP DATABASE IF EXISTS mybatis_test;
CREATE DATABASE mybatis_test DEFAULT CHARACTER SET utf8mb4;
-- 使⽤数据数据
USE mybatis_test;
-- 创建表[⽤⼾表]
DROP TABLE IF EXISTS userinfo;
CREATE TABLE `userinfo` (
`id` INT ( 11 ) NOT NULL AUTO_INCREMENT,
`username` VARCHAR ( 127 ) NOT NULL,
`password` VARCHAR ( 127 ) NOT NULL,
`age` TINYINT ( 4 ) NOT NULL,
`gender` TINYINT ( 4 ) DEFAULT '0' COMMENT '1-男 2-⼥ 0-默认',
`phone` VARCHAR ( 15 ) DEFAULT NULL,
`delete_flag` TINYINT ( 4 ) DEFAULT 0 COMMENT '0-正常, 1-删除',
`create_time` DATETIME DEFAULT now(),
`update_time` DATETIME DEFAULT now(),
PRIMARY KEY ( `id` )
) ENGINE = INNODB DEFAULT CHARSET = utf8mb4;
-- 添加⽤⼾信息
INSERT INTO mybatis_test.userinfo ( username, `password`, age, gender, phone )
VALUES ( 'admin', 'admin', 18, 1, '18612340001' );
INSERT INTO mybatis_test.userinfo ( username, `password`, age, gender, phone )
VALUES ( 'zhangsan', 'zhangsan', 18, 1, '18612340002' );
INSERT INTO mybatis_test.userinfo ( username, `password`, age, gender, phone )
VALUES ( 'lisi', 'lisi', 18, 1, '18612340003' );
INSERT INTO mybatis_test.userinfo ( username, `password`, age, gender, phone )
VALUES ( 'wangwu', 'wangwu', 18, 1, '18612340004' );
java 复制代码
import lombok.Data;
import java.util.Date;

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

配置数据库链接字符串

Mybatis中要连接数据库,需要数据库相关参数配置,在项目的配置文件中添加这些配置.

java 复制代码
#驱动类名称
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=123456

编写持久层代码

在项⽬中,创建持久层接UserInfoMapper.

java 复制代码
@Mapper
public interface UserInfoMapper {

    @Select("select * from userinfo")
    List<UserInfo> getUserInfoAll();
}

单元测试

在test目录下对接口进行测试

java 复制代码
@SpringBootTest
class UserInfoMapperTest {
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Test
    void getUserInfoAll() {
        List<UserInfo> userInfos = userInfoMapper.getUserInfoAll();
        for (UserInfo userInfo : userInfos) {
            System.out.println(userInfo);
        }
    }
}

允许结果与数据库信息相符,接口与链接均正常.

MyBatis基础操作

打印日志

在MyBatis中,可以通过打印日志看到sql语句的执行,执行过程中传递的参数以及执行的结果.在配置文件中添加以下配置即可.

java 复制代码
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

日志中包含多个信息:

红框中为执行的sql语句.

蓝框为传递的参数及其类型.

橙框为执行的结果.

传递参数

在操作数据库的应用中,经常需要指定一些参数来进行精准的操作.如果这些参数直接写在sql上,那么代码就会变得很繁琐.

解决⽅案:在⽅法中添加⼀个参数(id),将⽅法中的参数,传给sql语句.在sql语句中使用#{}来获取到方法中提供的参数.

java 复制代码
    //查询代码:
    @Select("select * from userinfo where id = #{id}")
    List<UserInfo> getUserInfoById(Integer id);
    //测试代码:
    @Test
    void getUserInfoById() {
        List<UserInfo> userInfos = userInfoMapper.getUserInfoById(2);
        for (UserInfo userInfo : userInfos) {
            System.out.println(userInfo);
        }
    }

从日志中观察到,sql语句中的id=后面为"?",是JDBC中所使用的占位符,参数列表中传递了Integer类型的值为2参数,查询的结果也为id=2,可见传递的参数正常到达数据库中.

也可以使用@Param设置别名,如果使⽤@Param设置别名,#{}⾥⾯的属性名必须和@Param 设置的⼀样.

java 复制代码
    //将id设置为di
    @Select("select * from userinfo where id = #{di}")
    List<UserInfo> getUserInfoByIdParam(@Param("di") Integer id);
    @Test
    void getUserInfoByIdParam() {
        List<UserInfo> userInfos = userInfoMapper.getUserInfoByIdParam(2);
        for (UserInfo userInfo : userInfos) {
            System.out.println(userInfo);
        }
    }

执行结果正常.

Insert

插入的sql语句使用关键字Insert,在MyBatis中使用注解@Insert标识插入操作:

java 复制代码
    @Insert("insert into userinfo(name, password, age, gender) " +
            "values (#{username},#{password},#{age},#{gender})")
    //从对象中解析所需的参数
    Integer insertUserInfo(UserInfo userInfo);

返回值类型为Integer,表示插入影响到了几行.

java 复制代码
    @Test
    void insertUserInfo() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("qianqi");
        userInfo.setPassword("123456");
        userInfo.setAge(19);
        userInfo.setGender(0);
        //直接传递对象
        int n = userInfoMapper.insertUserInfo(userInfo);
        System.out.println("插入影响到了"+n+"行");
    }

返回主键:

在插入成功后,我们有时需要获得新插入的自增主键,如上面的id,如果想要拿到⾃增id,需要在Mapper接⼝的⽅法上添加⼀个Options的注解.将Options注解的useGeneratedKeys设置为true,将keyProperty设置为想要获得的主键名,如id.再使用对象的getId来获取到自增主键id.

java 复制代码
    @Options(useGeneratedKeys = true,keyProperty = "id")
    @Insert("insert into userinfo(username, password, age, gender) " +
            "values (#{username},#{password},#{age},#{gender})")
    Integer insertUserInfo(UserInfo userInfo);
    @Test
    void insertUserInfo() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("qianqi");
        userInfo.setPassword("123456");
        userInfo.setAge(19);
        userInfo.setGender(0);
        int n = userInfoMapper.insertUserInfo(userInfo);
        System.out.println("插入影响到了"+n+"行,数据id:"+userInfo.getId());
    }

Delete

删除的使用方式与插入类似,将注释改为@Delete即可.

java 复制代码
    @Delete("delete from userinfo where id = #{id}")
    Integer deleteUserInfo(Integer id);
    @Test
    void deleteUserInfo() {
        int n = userInfoMapper.deleteUserInfo(7);
        System.out.println("删除影响到了"+n+"行");
    }

执行程序并刷新数据库,发现删除成功.

Update

修改的操作与之前类似,捡修饰符修改为@Update即可.

java 复制代码
    @Update("Update userinfo set age = 114514 where id = #{id}")
    Integer updateUserInfo(Integer id);    
    @Test
    void updateUserInfo() {
        int n = userInfoMapper.updateUserInfo(6);
        System.out.println("修改影响到了"+n+"行");
    }

执行程序,观察数据库,发现结果正确.

Select

在上⾯查询时发现,有⼏个字段是没有赋值的,只有Java对象属性和数据库字段⼀模⼀样时,才会进⾏赋值.

SQL语句中,查询了delete_flag,create_time,update_time,但是这⼏个属性却没有给deleteFlag,createTime,updateTime赋值.

当⾃动映射查询结果时,MyBatis会获取结果中返回的列名并在Java类中查找相同名字的属性,忽略大小写.然而在数据库中的命名规范与Java的命名规范是不相同的,想要双方命名一致不可寻,我们只能另寻他法.

起别名

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

java 复制代码
    @Select("select id, username, password, age, gender, phone, " +
            "delete_flag as deleteFlag,create_time as createTime," +
            " update_time as updateTime from userinfo")
    public List<UserInfo> getUserInfoAllParam();
    @Test
    void getUserInfoAllParam() {
        List<UserInfo> userInfos = userInfoMapper.getUserInfoAllParam();
        for (UserInfo userInfo : userInfos) {
            System.out.println(userInfo);
        }
    }

在sql语句中起别名后,MyBatis就可以识别到返回的列名于Java类的属性名一直,从而进行赋值.

结果映射

使用@Results关键字对返回的结果进行映射,也就是将列名于Java属性名"绑定"起来.示例:@Result(column = "delete_flag",property = "deleteFlag"),在使用多个映射时,需要将这些映射语句装载到同一个@Result中:

java 复制代码
    @Select("select * from userinfo")
    @Results({
            @Result(column = "delete_flag",property = "deleteFlag"),
            @Result(column = "create_time",property = "createTime"),
            @Result(column = "update_time",property = "updateTime")
    })
    List<UserInfo> getUserInfoAll2();
    @Test
    void getUserInfoAll2() {
        List<UserInfo> userInfos = userInfoMapper.getUserInfoAll2();
        for (UserInfo userInfo : userInfos) {
            System.out.println(userInfo);
        }
    }
开启驼峰命名

通常数据库列使⽤蛇形命名法进⾏命名(下划线分割各个单词),⽽Java属性⼀般遵循驼峰命名法约定.为了在这两种命名⽅式之间启⽤⾃动映射,需要将配置文件中的mapUnderscoreToCamelCase设置为true即可.名称转换实例:abc_def -> abcDef.

java 复制代码
#开启驼峰转换
mybatis.configuration.map-underscore-to-camel-case=true

再次运行一开始的查询代码:

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

正确的将数据库中的下划线命名转换为Java中的驼峰命名并赋值.

相关推荐
zfoo-framework3 小时前
使用VisualVM进行java性能瓶颈定位 1.无需像JProfiler那样必须加启动参数???
java
-Initiation3 小时前
数据库的安全与保护
数据库·安全
蔚蓝星辰mic3 小时前
数据库运维查询SQL语句集合
数据库·sql·1024程序员节
bug攻城狮3 小时前
Spring Boot 2.6+ 整合 PageHelper 启动报错:循环依赖解决方案全解析
java·spring boot·后端
好学且牛逼的马4 小时前
MyBatis-Plus的深度解析
java
苏纪云4 小时前
数据结构<C++>——数组
java·数据结构·c++·数组·动态数组
NocoBase4 小时前
8 人团队如何效率拉满?——创联云的开发方法论
数据库·低代码·开源
典则4 小时前
STM32FreeRtos入门(五)——同步互斥与通信
java·jvm·stm32
你不是我我4 小时前
【Java 开发日记】我们来讲一讲阻塞队列及其应用
java·开发语言