利用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));
    }


测试结果:


目录
相关文章
|
2天前
|
SQL 存储 Java
基于MyBatis的增删改查操作
基于MyBatis的增删改查操作
8 1
|
1天前
|
XML Java 数据库连接
【MyBatis】MyBatis操作数据库(一)
【MyBatis】MyBatis操作数据库(一)
9 1
|
1天前
|
SQL XML Java
【MyBatis】 MyBatis框架下的高效数据操作:深入理解增删查改(CRUD)
【MyBatis】 MyBatis框架下的高效数据操作:深入理解增删查改(CRUD)
6 1
|
1天前
|
Java 关系型数据库 数据库连接
【MyBatis】初步解析MyBatis:实现数据库交互与关系映射的全面指南
【MyBatis】初步解析MyBatis:实现数据库交互与关系映射的全面指南
7 1
|
1天前
|
SQL Java 数据库连接
【MyBatis】深入解析MyBatis:高效操作数据库技术详解
【MyBatis】深入解析MyBatis:高效操作数据库技术详解
17 0
|
1天前
|
SQL Java 数据库连接
【MyBatis】MyBatis操作数据库(二):动态SQL、#{}与${}的区别
【MyBatis】MyBatis操作数据库(二):动态SQL、#{}与${}的区别
7 0
|
2天前
|
存储 关系型数据库 MySQL
关系型数据库mysql日志和临时文件
【6月更文挑战第15天】
18 4
|
2天前
|
存储 关系型数据库 MySQL
关系型数据库mysql数据文件存储
【6月更文挑战第15天】
9 4
|
2天前
|
存储 关系型数据库 MySQL
关系型数据库mysql文件系统支持
【6月更文挑战第15天】
19 4
|
3天前
|
存储 自然语言处理 关系型数据库

热门文章

最新文章