Mybatis的快速入门

2023-12-27 14:42:37

专栏精选

引入Mybatis

摘要

上一篇文章中我们介绍了如何使用JDBC实现一个简单的表格查询功能,今天,我们将使用Mybatis实现同样的功能,通过对比这两次不同的实现我们可以明确感受到JDBC和Mybatis的不同。此外,在本文还将简单介绍Mybatis的简单增删改查操作方法,包括基于xml文件和基于注解两种方式。文中的很多内容都能在一定程度上让我们的开发之旅更加轻松方便,这是一个菜鸟提升技术能力,老鸟巩固基础知识的好机会。准备好开启今天的神奇之旅了吗?

引言

大家好,我是奇迹老李,一个专注于分享开发经验和基础教程的博主。这里是我的其中一个技术分享平台,欢迎广大朋友们点赞评论提出意见,重要的是点击关注喔 🙆。今天要和大家分享的内容是Mybatis的快速入门。做好准备,Let’s go🚎🚀

正文

在这里插入图片描述

通过Mybatis实现简单的查询

在这里插入图片描述

还是这个简单的查询功能,在上一篇文章中我们通过JDBC实现了这个查询,今天我们通过Mybatis来实现相同的功能,包括如下几个步骤:

  1. 编辑配置
  2. 读取配置
  3. 建立SQL映射(包括mapper文件和接口)
  4. 实现业务功能
  5. 编辑结果映射

编辑配置

一个简单的Mybatis配置文件内容如下代码所示。其中各个配置项的实际意义我们将在后续的文章中陆续解释,这里直接复制代码即可

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!--外部资源-->
    <properties resource="mysql-env.properties"/>
	<!--配置数据源-->
    <environments default="mysql">
        <environment id="mysql">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>
	<!--配置映射文件位置-->
    <mappers>
        <mapper resource="mapper/ApplicationMapper.xml"/>
    </mappers>
</configuration>

读取配置

package top.sunyog.mybatis;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import top.sunyog.common.entity.AppSearchVo;
import top.sunyog.common.entity.AppTestEntity;
import top.sunyog.mybatis.mapper.ApplicationRepository;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class MybatisApp {
    public static void main(String[] args) {
        try (InputStream in = MybatisApp.class.getResourceAsStream("/mybatis-config.xml")) {
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory sqlSessionFactory = builder.build(in);

            ...
        } catch (IOException e) {
            System.out.println("资源路径错误");
        }
    }
}

建立SQL映射

包括接口和xml文件,mapper接口如下:

package top.sunyog.mybatis.mapper;

import top.sunyog.common.entity.AppSearchVo;
import top.sunyog.common.entity.AppTestEntity;

import java.util.List;

public interface ApplicationRepository {
    List<AppTestEntity> queryApp(AppSearchVo param);
}

mapper映射xml文件如下

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="top.sunyog.mybatis.mapper.ApplicationRepository">
    ...
    <select id="queryApp" resultType="top.sunyog.common.entity.AppTestEntity">
        select id,app_name,app_code,auth_type,create_date,creator from app_test
        <where>
            <if test="null != appName and ''.toString() != appName">and app_name like concat('%',#{appName},'%')</if>
            <if test="null != authType and ''.toString() != authType">and auth_type = #{authType}</if>
            <if test="null != startDate and '' != startDate">and create_date >= #{startDate}</if>
            <if test="null != endDate and '' != endDate">and create_date &lt;= #{endDate}</if>
        </where>
    </select>
</mapper>


AppTestEntity类的具体代码如下

public class AppTestEntity {
    private Long id;
    private String appName;
    private String appCode;
    private String authType;
    private LocalDate createDate;
    private String creator;
    private String appStatus;
    //省略getter、setter、to'S方法
}

实现业务功能

...
public class MybatisApp {
    public static void main(String[] args) {
        try (InputStream in = MybatisApp.class.getResourceAsStream("/mybatis-config.xml")) {
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory sqlSessionFactory = builder.build(in);

            AppSearchVo param = new AppSearchVo();
            param.setAppName("应用");
            param.setAuthType("2");
            SqlSession session = sqlSessionFactory.openSession();
            ApplicationRepository mapper = session.getMapper(ApplicationRepository.class);
            List<AppTestEntity> list = mapper.queryApp(param);
            list.forEach(o-> System.out.println(o));
            session.close();
        } catch (IOException e) {
            System.out.println("资源路径错误");
        }
    }
}

按照以上步骤执行后,会发现打印出的结果都是空数据,这是由于数据库中app_test表的字段名和AppTestEntity类的属性名不一致,没有映射成功导致的,解决这个问题有两种方式

编辑结果映射

结果映射的方式有两种可以通过ResultMap标签直接编辑,也可以通过配置Mybatis的自动映射实现该功能

  1. 通过ResultMap映射

    <mapper namespace="...">
    	<resultMap id="appTestMap" type="top.sunyog.common.entity.AppTestEntity">
         <result column="app_name" property="appName"/>
         <result column="app_code" property="appCode"/>
         <result column="auth_type" property="authType"/>
         <result column="create_date" property="createDate"/>
     </resultMap>
        
     <select id="queryApp" resultMap="appTestMap">...</select>
    </mapper>
    
  2. 在配置文件中配置mapUnderscoreToCamelCasetrue,使用这种方式需要保证数据库中的字段下划线命名和java类中的驼峰命名一一对应

    <configuration>
        <properties .../>
        
        <settings>
            <setting name="mapUnderscoreToCamelCase" value="true"/>
        </settings>
        
        <environments .../>
        
        <mappers>
        	...
        </mappers>
    </configuration>
    

对以上内容的简单说明

配置文件中的 mysql-env.properties文件内容为

driver=com.mysql.cj.jdbc.Driver
#需替换为自己数据库url
url=jdbc:mysql://localhost:3306/sunyog_db?serverTimezone=Asia/Shanghai
username=你自己的用户名
password=你自己的没密码

项目的具体目录结构如下

mybatis-demo
	|-src
		|-main
			|-java
				|-top
					|-sunyog
						|-common
							|-entity
								|-AppTestEntity.java
						|-mybatis
							|-mapper
								|-ApplicationRepository.java
							|-MybatisApp.java
			|-resources
				|-mapper
					|-ApplicationMapper.xml
				|-mysql-env.properties
				|-mybatis-config.xml
		|-test
			|-java
			|-resources

Mybatis的简单CRUD

在mybatis的mapper文件中,以下标签分别对应数据库的增、删、改、查操作

<insert id="" parameterType=""></insert>
<delete id=""></delete>
<update id="" parameterType=""></update>
<select id="" resultType=""></select>

为了方便测试,我们对之前的main方法进行改造,改造后的效果如下

public class MybatisApp {
    public static void main(String[] args) {
        SqlSession session=null;
        try (InputStream in = MybatisApp.class.getResourceAsStream("/mybatis-config.xml")) {
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory sqlSessionFactory = builder.build(in);

            session = sqlSessionFactory.openSession();
            ApplicationRepository mapper = session.getMapper(ApplicationRepository.class);

//            testInsert(mapper);
            testDelete(mapper);
//            testUpdate(mapper);
//            testQuery(mapper);

            session.commit();
        } catch (IOException e) {
            System.out.println("资源路径错误");
        } finally {
            if (session!=null){
                session.close();
            }
        }
    }
}

//mapper接口
int addApp(AppTestEntity entity);    
<mapper>
    <insert id="addApp" parameterType="top.sunyog.common.entity.AppTestEntity">
        insert into app_test(app_name,app_code,auth_type,create_date,creator)
        values(#{appName},#{appCode},#{authType},#{createDate},#{creator})
    </insert>
</mapper>
//测试代码
private static void testInsert(ApplicationRepository mapper) {
    AppTestEntity entity = new AppTestEntity();
    entity.setAppName("测试新增");
    entity.setAppCode("test_add_app");
    entity.setAuthType("2");
    entity.setCreateDate(LocalDate.now());
    entity.setCreator("admin2");
    int row = mapper.addApp(entity);
    System.out.println("新增成功, 影响行数: "+row);
}    

以下代码具有和xml映射文件同等的作用

@Insert("insert into app_test(app_name,app_code,auth_type,create_date,creator)"+
        "values(#{appName},#{appCode},#{authType},#{createDate},#{creator})")
int addApp(AppTestEntity entity); 

int deleteById(Long id);
<mapper>
	<delete id="deleteById" parameterType="long">
        delete from app_test where id=#{id}
    </delete>
</mapper>
private static void testDelete(ApplicationRepository mapper) {
    int row = mapper.deleteById(4L);
    System.out.println("删除成功,影响行数: "+row);
}

以下代码具有同等作用

@Delete("delete from app_test where id=#{id}")
int deleteById(Long id);

int updateById(AppTestEntity entity);
<mapper>
	<update id="updateById" parameterType="top.sunyog.common.entity.AppTestEntity">
<!--        update app_test set app_name=#{appName},app_code=#{appCode},auth_type=#{authType},create_date=#{createDate},-->
<!--            creator=#{creator} where id=#{id}-->
        update app_test
        <set>
            <if test="appName != null and '' != appName">app_name = #{appName},</if>
            <if test="appCode != null and '' != appCode">app_code = #{appCode},</if>
            <if test="authType != null and '' != authType">auth_type = #{authType},</if>
            <if test="createDate != null and '' != createDate">create_date = #{createDate},</if>
            <if test="creator != null and '' != creator">creator = #{creator},</if>
        </set>
        where id=#{id}
    </update>
</mapper>	
private static void testUpdate(ApplicationRepository mapper) {
    AppTestEntity entity = new AppTestEntity();
    //        entity.setAppName("测试修改3");
    entity.setId(4L);
    //        entity.setAppCode("test_update_app");
    entity.setAuthType("2");
    //        entity.setCreateDate(LocalDate.now());
    //        entity.setCreator("zhangsan");
    int row = mapper.updateById(entity);
    System.out.println("修改成功,影响行数: "+row);
}

更新操作中存在动态sql标签,直接使用 @Update 注解会使代码变复杂,后续动态sql章节详细介绍基于注解的写法。

通过ID查询

AppTestEntity queryById(Long id);
<mapper>
    <select id="queryById" resultType="top.sunyog.common.entity.AppTestEntity">
        select id,app_name,app_code,auth_type,create_date,creator from app_test where id=#{id} limit 0,1
    </select>
</mapper>
private static void testOne(ApplicationRepository mapper) {
    AppTestEntity entity = mapper.queryById(1L);
    System.out.println(entity);
}

以下代码具有同等作用

@Select("select id,app_name,app_code,auth_type,create_date,creator from app_test where id=#{id} limit 0,1")
AppTestEntity queryById(Long id);

通过条件查询列表

List<AppTestEntity> queryApps(Map map);
<select id="queryApp" resultType="top.sunyog.common.entity.AppTestEntity">
    select id, app_name, app_code, auth_type, create_date, creator from app_test
    <where>
        <if test="null != appName and ''.toString() != appName">and app_name like concat('% ',#{appName},' %')</if>
        <if test="null != authType and ''.toString() != authType">and auth_type = #{authType}</if>
        <if test="null != startDate and '' != startDate">and create_date >= #{startDate}</if>
        <if test="null != endDate and '' != endDate">and create_date &lt;= #{endDate}</if>
    </where>
</select>
private static void testList(ApplicationRepository mapper) {
	Map<String,Object> map=new HashMap(8);
    map.put("appName","测试");
    map.put("endDate",new Date());
    List<AppTestEntity> entitys = mapper.queryApps(1L);
    System.out.println(entitys);
}

可优化的点

以上代码存在的问题

  1. xml标签中parameterTypeparameterType元素写类全名过长

  2. 列表查询和单个查询中存在重复代码

  3. 删除功能在业务上一般都是逻辑删除

  4. insert语句新增的不一定是单行数据,可能是一个数组或list列表

这些问题我们将在后续的文章中进行一一分析

总结

在这篇文章中,我们介绍了mybatis的最基础用法,同时实现了一个简单的表格查询功能,通过对比JDBC的实现和Mybatis的实现我们可以看出,相比与JDBC,使用Mybatis框架进行开发具有很多优点

  1. 通过配置改变Mybatis的行为,如本文中的 mapUnderscoreToCamelCase配置项
  2. 自动实现数据库表和java对象之间的映射
  3. 自定义数据库表和java对象之间的映射行为
  4. 动态创建sql语句
  5. 将业务逻辑和数据库操作解耦

📩 联系方式
邮箱:qijilaoli@foxmail.com

?版权声明
本文为原创文章,版权归作者所有。未经许可,禁止转载。更多内容请访问奇迹老李的博客首页

文章来源:https://blog.csdn.net/qq_43408971/article/details/135219819
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。