利用MyBatis框架操作数据库1

本文涉及的产品
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
简介: 利用MyBatis框架操作数据库

一、MyBatis框架简介

MyBatis是一个持久化框架,支持自定义SQL、存储过程以及高级映射,是一个优秀的ORM(对象关系映射)的框架。

MyBatis框架的特点就是比较灵活。

二、创建Mybatis项目

1、在Mysql中创建要进行操作的数据库和数据表。

2、创建项目并添加MyBatis依赖

#配置数据库的连接信息
spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/mycnblog?characterEncoding=utf8
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver

3、配置MyBatis连接字符串以及保存的xml目录。

配置数据库连接信息:

#配置数据库的连接信息
spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/mycnblog?characterEncoding=utf8
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver

xml文件保存路径:

#设置MyBatis的xml保存路径
mybatis:
  mapper-locations: classpath:mybatis/**Mapper.xml

4、添加业务代码

a、创建model包,添加UserInfo实体类:

@Data
public class UserInfo {
    private Integer id;
    private String username;
    private String password;
    private String photo;
    private String createTime;
    private String updateTime;
    private int state;
}

b、创建mapper包,定义UserMapper接口:

@Mapper
public interface UserMapper {
    public UserInfo getUserInfoById(@Param("id") Integer id);
 
}

在resources目录下创建mybatis文件夹,创建UserMapper.xml文件,文件内容如下,其中select标签的id表示要执行的方法名,resultType表示返回的类的路径:

<?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.mybatisdemo.mapper.UserMapper">
    <select id="getUserInfoById" resultType="com.example.mybatisdemo.model.UserInfo">
        select * from userinfo where id=${id}
    </select>
</mapper>

创建service包,创建UserService类,获取到UserMapper并实现getUserInfoById方法:

@Service
public class UserService {
    @Resource
    public UserMapper userMapper;
    public UserInfo getUserInfoById(Integer id){
        return userMapper.getUserInfoById(id);
    }
}

创建controller包,创建UserController类,获取到UserService类并实现getUserInfoById方法:

@Controller
public class UserController {
    @Autowired
    private UserService userService;
    @ResponseBody
    @RequestMapping("/getuserinbyid")
    public UserInfo getUserInfoById(Integer id){
        if(id == null){
            return null;
        }
        return userService.getUserInfoById(id);
    }
}

访问验证:

三、利用MyBatis操作数据库

在操作数据库之前,首先了解一下单元测试,单元测试可以针对某一方法进行测试,并且不需要再启动SpringBoot项目,使用单元测试有如下好处:

  • 使用单元测试可以非常直观、简单地测试某一功能的正确性;
  • 使用单元测试可以帮助在打包的时候发现一些错误,因为在打包之前要求所有的单元测试都必须通过。
  • 使用单元测试不会对原有的数据库造成污染。

如果不想对数据库造成污染,就需要添加@Transactional注解,其原理是先执行sql语句,在进行回滚操作。

使用单元测试的一般步骤:

先生成单元测试的类:

在接口中右击鼠标,单击generate:

选择test,出现如下界面:

点击ok之后就会自动生成测试类。

增加数据

增加一条用户信息,并返回受影响的行数。

首先需要在UserMapper接口中声明方法。

 //添加用户信息,返回受影响的行数
    public int addUserInfo(UserInfo userInfo);

然后需要在resources文件夹下的MyBatis文件下的UserMapper.xml文件中新增如下的insert标签:

<!--增加用户信息,返回受影响的行数 -->
    <insert id="addUserInfo">
        insert into userinfo(id,username,password,photo) values(#{id},#{username},#{password},#{photo})
    </insert>

在生成的测试类中编写代码:

    @Test
    void addUserInfo() {
        UserInfo userInfo = new UserInfo();
        userInfo.setId(2);
        userInfo.setUsername("lucy");
        userInfo.setPassword("1234");
        userInfo.setPhoto("test.jpg");
        int i =userMapper.addUserInfo(userInfo);
        Assertions.assertEquals(1,i);//使用断言测试返回受影响的行数是否为1
    }


启动单元测试的结果:

由于当时在新建数据表时id是默认自增的,就需要在xml文件中的 insert添加如下属性:

<!--增加用户信息,返回受影响的行数 如下参数表示id为自增的-->
    <insert id="addUserInfo" useGeneratedKeys="true" keyProperty="id" keyColumn="id">
        insert into userinfo(username,password,photo) values(#{username},#{password},#{photo})
    </insert>

删除数据

删除指定id的用户信息,并返回受影响的行数。

在UserMapper接口中定义删除数据的方法:

@Transactional //删除用户信息不污染数据库
    //根据ID查询User信息
    public int deleteUserInfo(@Param("id") Integer id);

在xml文件下添加delete标签:

    <!-- 通过指定id删除用户信息 -->
    <delete id="deleteUserInfo">
        delete from userinfo where id=#{id}
    </delete>

在测试类中编写代码:

    //根据ID删除UserInfo信息
    @Test
    void deleteUserInfo() {
        int i =userMapper.deleteUserInfo(3);
        Assertions.assertEquals(1,i);//使用断言测试返回受影响的行数是否为1
    }

启动单元测试运行结果:

修改数据

修改指定id的用户名。

在UserMapper接口中定义修改数据方法:

//根据id修改用户名
    public int updateUserInfo(@Param("id") Integer id,@Param("username") String username);

在xml文件中添加update标签:

<!--指定id修改用户名-->
    <update id="updateUserInfo">
        update userinfo set username=#{username} where id=${id}
    </update>

在生成的测试类中编写测试代码:

//根据id修改用户名
    @Test
    void updateUserInfo() {
        int i = userMapper.updateUserInfo(2,"mary");
        Assertions.assertEquals(1,i);//使用断言测试返回受影响的行数是否为1
    }

测试运行结果:

查询数据

根据id查询用户信息。

在UserMapper中定义查询方法:

@Transactional
    //根据id查询UserInfo信息
    public UserInfo getUserInfoById(@Param("id") Integer id);

在xml文件中添加select标签,其中resultType标签表示返回的对象所属类的路径

<!-- 通过id查询用户信息 -->
    <select id="getUserInfoById" resultType="com.example.mybatisdemo.model.UserInfo">
        select * from userinfo where id=${id}
    </select>

在测试类中编写测试代码:

//通过id查询用户信息
    @Test
    void getUserInfoById() {
        UserInfo userInfo = userMapper.getUserInfoById(1);
        Assertions.assertNotNull(userInfo);
    }

测试运行结果:

在之前的xml文件中使用${}和#{} 这两种参数占位符,那么这两种占位符有如下区别:

定义不同:${}直接替换,#{}会进行预处理;

用法不同:${}只适用于整数替换,#{}适合所有的数据类型;

安全性不同:${}会导致sql注入安全问题,#{}的性能高,并且不存在安全问题。

${}如何会引起sql注入呢?

在userinfo信息表中有username和password两个属性,那么在查询的时候给password属性传入‘or 1= ‘1’’就会导致查出所有的用户信息包含用户的密码:

xml文件中新增如下的select标签:

<!-- 通过用户名和密码查询用户信息 -->
    <select id="getUserInfoByNameAndPwd" resultType="com.example.mybatisdemo.model.UserInfo">
        select * from userinfo where username='${username}' and password=${password}
    </select>

使用如下测试代码:

 //根据用户名和密码查询用户信息
    @Test
    void getUserInfoByNameAndPwd() {
        String username = "admin";
        String password = "''or 1 ='1'";
        userMapper.getUserInfoByNameAndPwd(username,password);
    }

查询到了所有的userinfo导致sql注入问题:

但是将参数占位符换为#{},再进行测试:

#{}占位符会进行预处理,不会直接进行替换,就不会出现sql注入的问题。

那么?{}就没有应用场景了吗?答案当然是否定的,任何东西存在即合理,当传递的参数是sql关键字或sql命令时就需要使用?{}占位符,因为需要直接替换,不需要#{}来进行预处理为字符串,否则就会报错。

利用MyBatis框架操作数据库2:https://developer.aliyun.com/article/1521802?spm=a2c6h.13148508.setting.18.55b44f0eiXO8eW

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
目录
相关文章
SQL XML Java
141 0
|
4月前
|
SQL Java 数据库连接
区分iBatis与MyBatis:两个Java数据库框架的比较
总结起来:虽然从技术角度看,iBATIS已经停止更新但仍然可用;然而考虑到长期项目健康度及未来可能需求变化情况下MYBATISS无疑会是一个更佳选择因其具备良好生命周期管理机制同时也因为社区力量背书确保问题修复新特征添加速度快捷有效.
256 12
|
5月前
|
SQL XML Java
MyBatis框架如何处理字符串相等的判断条件。
总的来说,MyBatis框架提供了灵活而强大的机制来处理SQL语句中的字符串相等判断条件。无论是简单的等值判断,还是复杂的条件逻辑,MyBatis都能通过其标签和属性来实现,使得动态SQL的编写既安全又高效。
342 0
|
6月前
|
SQL XML Java
配置Spring框架以连接SQL Server数据库
最后,需要集成Spring配置到应用中,这通常在 `main`方法或者Spring Boot的应用配置类中通过加载XML配置或使用注解来实现。
516 0
|
8月前
|
人工智能 数据挖掘 API
基于neo4j数据库和dify大模型框架的rag模型搭建——后续补充
基于neo4j数据库和dify大模型框架的rag模型搭建——后续补充
863 21
基于neo4j数据库和dify大模型框架的rag模型搭建——后续补充
|
8月前
|
Java 数据库 Docker
基于neo4j数据库和dify大模型框架的rag模型搭建
基于neo4j数据库和dify大模型框架的rag模型搭建
2230 35
|
9月前
|
SQL 数据库连接 数据库
在C++的QT框架中实现SQLite数据库的连接与操作
以上就是在C++的QT框架中实现SQLite数据库的连接与操作的基本步骤。这些步骤包括创建数据库连接、执行SQL命令、处理查询结果和关闭数据库连接。在实际使用中,你可能需要根据具体的需求来修改这些代码。
557 14
|
10月前
|
Oracle 关系型数据库 Java
|
4月前
|
关系型数据库 MySQL 分布式数据库
阿里云PolarDB云原生数据库收费价格:MySQL和PostgreSQL详细介绍
阿里云PolarDB兼容MySQL、PostgreSQL及Oracle语法,支持集中式与分布式架构。标准版2核4G年费1116元起,企业版最高性能达4核16G,支持HTAP与多级高可用,广泛应用于金融、政务、互联网等领域,TCO成本降低50%。
|
4月前
|
SQL 关系型数据库 MySQL
Mysql数据恢复—Mysql数据库delete删除后数据恢复案例
本地服务器,操作系统为windows server。服务器上部署mysql单实例,innodb引擎,独立表空间。未进行数据库备份,未开启binlog。 人为误操作使用Delete命令删除数据时未添加where子句,导致全表数据被删除。删除后未对该表进行任何操作。需要恢复误删除的数据。 在本案例中的mysql数据库未进行备份,也未开启binlog日志,无法直接还原数据库。