利用MyBatis框架操作数据库2

简介: 利用MyBatis框架操作数据库

利用MyBatis框架操作数据库1:https://developer.aliyun.com/article/1521801

like 模糊查询

在sql语句进行查询时也会经常用到like模糊查询,%表示0或多个字符,_表示一个字符,那么先使用?{}占位符来查询username中含有‘a’字符的用户信息。

xml的select标签的信息如下:

<select id="getUserInfoByLike" resultType="com.example.mybatisdemo.model.UserInfo">
        select * from userinfo where username like %?{username}%
</select>

测试结果:

并不能完成直接替换,那么使用#{}参数占位符来进行测试,测试结果如下:

这两种参数占位符都不能直接实现模糊查询,就需要使用mysql中的内置函数concat来进行处理,将xml文件中的select标签的内容修改如下:

    <!-- 模糊查询用户信息-->
    <select id="getUserInfoByLike" resultType="com.example.mybatisdemo.model.UserInfo">
        select * from userinfo where username like concat('%',#{username},'%')
    </select>

测试结果如下:

多表查询

上述的操作都是在单表的基础上进行,但是查询还存在多表查询,常见的表关系有一对一、一对多和多对多,那么利用MyBatis就可以实现一对一和一对多的多表查询。

一对一的多表查询

在mycnblog数据库中有userinfo和articleinfo表,两个表的字段设置如下所示:

其中articleinfo表的uid对应userinfo表的的id。

查询文章对应的用户信息。

首先在model包下创建ArticleInfo类,将articleinfo表的字段作为ArticleInfo类的属性,并添加UserInfo属性。

@Data
public class ArticleInfo {
    private int id;
    private String title;
    private String content;
    private String createtime;
    private String updatetime;
    private int uid;
    private int rcount;
    private int state;
    private UserInfo userInfo;
}

在Mapper包下创建ArticleMapper接口,定义id获取文章信息的方法:

 //通过文章id来获取文章信息
    public ArticleInfo getUserInfoByArticleInfoId(@Param("id") Integer id);

在mybatis包下创建ArticleMapper.xml文件,添加select标签,由于要实现多表查询,select标签的ResultType标签就无法满足需求了,就需要添加一个resultMap标签, 其id为标签名,type为要映射的实体类的路径,在该标签中设置主键(id)和其他普通的字段(result),其中column为数据库字段名,property为程序中的属性名,并且在UserMapper.xml文件中也添加resultMap标签,然后在ArticleMapper.xml的resultMap标签中继续添加association标签,property代表要连接的表在程序中的属性名,resultMap为UserMapper.xml文件中的resultMap标签名称,由于userinfo表和articleinfo表中有同名的字段名,就使用columnPrefix属性,表示在原有字段名前添加设置的columnPrefix属性值,UserMapper.xml文件的resultMap标签如下:

<resultMap id="baseMapper" type="com.example.mybatisdemo.model.UserInfo">
        <!--设置主键属性-->
        <id column="id" property="id"></id>
        <!--设置其他属性-->
        <result column="username" property="username"></result>
        <result column="password" property="password"></result>
        <result column="photo" property="photo"></result>
        <result column="username" property="username"></result>
        <result column="createtime" property="createtime"></result>
        <result column="updatetime" property="updatetime"></result>
        <result column="state" property="state"></result>
 </resultMap>

ArticleMapper.xml文件的内容如下:

<resultMap id="baseMapper" type="com.example.mybatisdemo.model.ArticleInfo">
        <!--设置主键-->
        <id column="id" property="id"></id>
        <!-- 设置其他属性-->
        <result column="title" property="title"></result>
        <result column="content" property="content"></result>
        <result column="createtime" property="createtime"></result>
        <result column="updatetime" property="updatetime"></result>
        <result column="uid" property="uid"></result>
        <result column="rcount" property="rcount"></result>
        <result column="state" property="state"></result>
        <association property="userInfo"
                     resultMap="com.example.mybatisdemo.mapper.UserMapper.baseMapper"
                     columnPrefix="u_">
        </association>
    </resultMap>
    <select id="getUserInfoByArticleInfoId" resultMap="baseMapper">
        select a.*,u.id u_id,u.username u_username,u.password u_password,u.photo u_photo from articleinfo a left join userinfo u on a.uid=u.id
        where a.id=#{id}
    </select>

最后在生成的test类中编写测试方法:

 //通过id获取文章信息,实现一对一的多表查询
    @Test
    void getUserInfoByArticleInfoId() {
        ArticleInfo articleInfo  = articleMapper.getUserInfoByArticleInfoId(1);
        log.info(String.valueOf(articleInfo));
    }

测试结果:

日志中的信息:

createtime等字段为null因为在查询的时候就没有select这些字段。

一对多的多表查询

一个用户对应多篇文章,就需要使用一对多的多表查询。

先在UserInfo类中增加一个存放文章信息的集合:

private List<ArticleInfo> atrlist;

然后再UserMapper接口中定义查询方法:

 //根据id查询用户信息,并实现一对多的多表查询
 public UserInfo getUserInfoAndArtInfoById(@Param("id") Integer id);

在UserMapper.xml文件的resultMap标签中添加collection标签,其属性与association标签的属性值类似:

<collection property="atrlist"
                    resultMap="com.example.mybatisdemo.mapper.ArticleMapper.baseMapper"
                    columnPrefix="a_">
</collection>

再添加select标签:

    <!-- 通过id获取到用户信息,实现一对多的多表查询-->
    <select id="getUserInfoAndArtInfoById" resultMap="baseMapper">
        select u.*,a.id a_id,a.title a_title,a.content a_content from userinfo u left join  articleinfo a on u.id=a.uid
        where u.id=#{id}
    </select>

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

    @Test
    void getUserInfoAndArtInfoById() {
        UserInfo userInfo = userMapper.getUserInfoAndArtInfoById(1);
        log.info(String.valueOf(userInfo));
    }

测试结果:

日志中的文章信息如下:

四、动态SQL

在上述的操作中都使用的是固定的参数,并且有时会多写,等都会出现报错,但动态SQL就能很好的解决上述问题。

if标签

if标签的test属性可以判断参数是否有值,如果没有值,就会隐藏if标签中的参数。

非必传的参数就可以使用if标签。

例如新增一个Userinfo信息,username和id为必传信息,但是photo信息为非必传。

那么UserMapper的insert标签如下:

<insert id="addUserInfoByIf">
        insert into userinfo(username,password
        <if test="photo!=null">
            ,photo
        </if>)
        values(#{username},#{password}
        <if test="photo!=null">
                    ,#{photo}
                </if>
                )
</insert>

在传入参数的时候未传入photo参数:

@Test
    void addUserInfoByIf() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("老6");
        userInfo.setPassword("1234");
        int i = userMapper.addUserInfoByIf(userInfo);
        Assertions.assertEquals(1,i);
    }

测试结果:

trim标签

trim标签有如下的属性:

  • prefix:整个语句块,以prefix的值作为前缀;
  • suffix:整个语句块,以suffix的值作为后缀;
  • prefixOverrides:表示整个语句块要去除掉的前缀;
  • suffixOverrides:表示整个语句块要去除掉的后缀。

那么, 上面新增一个Userinfo信息就可以使用trim标签,修改xml标签的内容如下:

<insert id="addUserInfoByIf">
        insert into userinfo
        <trim prefix="(" suffix=")" suffixOverrides=",">   username,password
        <if test="photo!=null">
            ,photo
        </if>
        </trim>
        values
        <trim prefix="(" suffix=")" suffixOverrides=",">
        #{username},#{password}
        <if test="photo!=null">
                    ,#{photo}
                </if>
        </trim>
    </insert>


测试结果:

where标签

where标签可以实现查询中的where语句替换,如果where中没有任何查询条件,那么就会删除where语句,如果有查询条件,就会自动生成相应的sql语句,并可以自动去除最前面的and标签,where标签通常搭配if标签来进行使用。

例如利用名字和密码查询用户信息:

UserMapper.xml的查询标签如下所示:

 <!--通过where标签查询用户信息-->
    <select id="getUserInfoByWhere" resultType="com.example.mybatisdemo.model.UserInfo">
        select * from userinfo
        <where>
            <if test="username!=null">
                username=#{username}
            </if>
            <if test="password!=null">
               and password=#{password}
            </if>
        </where>
    </select>


当传入用户名和密码之后测试结果如下:

where标签也可以使用<trim>标签进行替换:

<trim prefix="where" suffixOverrides="and">

</trim>

set标签

set标签是针对update更新语句的,可以代替update标签中的set关键字来完成。

set标签通常需要搭配if标签来进行使用。

例如利用id来修改用户信息。

在xml文件中的update标签如下:

    <update id="updateUserInfoById">
        update userinfo
        <set>
            <if test="username!=null">
                username=#{username},
            </if>
            <if test="password!=null">
                password=#{password}
            </if>
        </set>
        where id=#{id}
    </update>

在测试类中的测试代码如下:

    @Test
    void updateUserInfoById() {
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("王五");
        userInfo.setPassword("9087");
        userInfo.setId(3);
        int i = userMapper.updateUserInfoById(userInfo);
        Assertions.assertNotNull(i);
    }

测试结果:

set标签也可以用trim标签进行替代

<trim prefix="set" suffixOverrides=",">

</trim>

foreach标签

对集合遍历时通常会使用该标签,在in关键字之后通常使用,该标签有如下的属性:

collection:绑定方法参数的集合,如List、Set、Map以及数组等;

item:遍历时的每个对象;

open:语句块开头的字符串;

close:语句块结束的字符串;

separator:每次遍历之间的字符串。

例如删除id在指定集合的用户信息:

xml文件中的delete标签如下:

    <delete id="deleteUserInfoByList">
        delete
        from userinfo
        where id in <foreach collection="list" item="uid" open="(" close=")" separator=",">
        #{uid}
    </foreach>
    </delete>

在生成的test类编写的测试代码如下:

    @Test
    void deleteUserInfoByList() {
        List<Integer> list = new LinkedList<>();
        list.add(4);
        list.add(3);
        list.add(5);
        int i = userMapper.deleteUserInfoByList(list);
        log.info(String.valueOf(i));
    }


测试结果:


目录
相关文章
|
14天前
|
缓存 Java 数据库连接
我们后端程序员不是操作MyBatis的CRUD Boy
大家好,我是南哥。一个对Java程序员进阶成长颇有研究的人,今天我们接着新的一篇Java进阶指南。为啥都戏称后端是CRUD Boy?难道就因为天天怼着数据库CRUD吗?要我说,是这个岗位的位置要的就是你CRUD,你不得不CRUD。哪有公司天天能给你搭建高并发、高可用、大数据框架的活呢,一条业务线总要成长吧,慢慢成熟了就要装修工来缝缝补补、美化美化,也就是CRUD的活。不能妄自菲薄CRUD Boy,我们是后端工程师。今天来指南下操作数据库之MyBatis框架。
我们后端程序员不是操作MyBatis的CRUD Boy
|
22小时前
|
SQL Java 数据库连接
Mybatis框架中SqlSessionFactory
Mybatis框架中SqlSessionFactory
|
4天前
|
SQL 数据库 Python
Django框架数据库ORM查询操作(6)
【7月更文挑战第6天】```markdown Django ORM常用数据库操作:1) 查询所有数据2) 根据ID查询 3) 精确查询 4) 分页排序
11 1
|
5天前
|
SQL 缓存 Java
使用MyBatis优化Java持久层操作
使用MyBatis优化Java持久层操作
|
15天前
|
Java Devops API
阿里云云效操作报错合集之云效页面提示数据库保存不进去,该怎么办
本合集将整理呈现用户在使用过程中遇到的报错及其对应的解决办法,包括但不限于账户权限设置错误、项目配置不正确、代码提交冲突、构建任务执行失败、测试环境异常、需求流转阻塞等问题。阿里云云效是一站式企业级研发协同和DevOps平台,为企业提供从需求规划、开发、测试、发布到运维、运营的全流程端到端服务和工具支撑,致力于提升企业的研发效能和创新能力。
|
2天前
|
SQL Java 数据库连接
Java面试题:简述ORM框架(如Hibernate、MyBatis)的工作原理及其优缺点。
Java面试题:简述ORM框架(如Hibernate、MyBatis)的工作原理及其优缺点。
5 0
|
5天前
|
SQL 缓存 Java
使用MyBatis优化Java持久层操作
使用MyBatis优化Java持久层操作
|
8天前
|
数据库
MybatisPlus3---常用注解,驼峰转下滑线作为表明 cteateTime 数据表中的 cteate_time,@TableField,与数据库字段冲突要使用转义字符“`order`“,is
MybatisPlus3---常用注解,驼峰转下滑线作为表明 cteateTime 数据表中的 cteate_time,@TableField,与数据库字段冲突要使用转义字符“`order`“,is
|
8天前
|
XML 关系型数据库 MySQL
支付系统----微信支付19---集成MyBatis-plus,数据库驱动对应的依赖版本设置问题,5没版本没有cj这个依赖,mysql驱动默认的是版本8,这里是一个父类,数据库都有,写个父类,继承就行
支付系统----微信支付19---集成MyBatis-plus,数据库驱动对应的依赖版本设置问题,5没版本没有cj这个依赖,mysql驱动默认的是版本8,这里是一个父类,数据库都有,写个父类,继承就行
|
8天前
|
关系型数据库 MySQL 数据库
MybatisPlus添加数据数据库没有数据,数据消失,使用Navicate看不到数据,Navicate中Mysql的数据与idea的数据不一定同步,Navicate与idea的数据库同步,其实有分页
MybatisPlus添加数据数据库没有数据,数据消失,使用Navicate看不到数据,Navicate中Mysql的数据与idea的数据不一定同步,Navicate与idea的数据库同步,其实有分页