什么是MyBatis

2023-10-26

一、MyBatis概述

1.1 原始的JDBC操作

谈及mybatis,必然需要先了解Java和数据库的连接技术——JDBC(Java DataBase Connectivity)。但是原始JDBC操作中,却存在如下缺点

  1. 数据库连接创建、释放频繁造成系统资源浪费从而影响系统性能。

  1. sql语句在代码中硬编译,造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变Java代码。

  1. 查询操作时,需要手动将结果集中的数据手动封装到实体中;插入操作时,需要手动将实体的数据设置到sql语句的占位符位置。

如下为原始JDBC操作:

public class JDBCDemo {
    public static void main(String[] args) throws Exception{
        //获取数据库连接对象
        Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db1","root","root");
        //定义sql语句
        String sql = "select * from db1.emp";
        //获取执行sql的对象Statement
        Statement stmt = conn.createStatement();
        //执行sql
        ResultSet resultSet = stmt.executeQuery(sql);
        //处理结果
        while(resultSet.next()) {             
            int id = resultSet.getInt(1);                    //获取id
            String name = resultSet.getString("ename");             //获取姓名
            System.out.println("id:" + id + " name:" + name);
        }
        //释放资源
        stmt.close();
        conn.close();
    }
}

1.2 如何克服JDBC固有缺陷

而面对上述缺点,我们的解决方案是:

  1. 使用数据库连接池技术(C3P0或者Druid)初始化连接资源;

  1. 将sql语句抽取到xml配置文件中(解耦合);

  1. 使用反射、内省等底层技术,自动将实体与表进行属性与字段的自动映射(比较困难)。

因此,mybatis应运而生!

1.3 什么是MyBatis

mybatis 是一个优秀的基于java的持久层框架,它内部封装了 jdbc,使开发者只需要关注sql语句本身,而不需要花费精力 去处理加载驱动、创建连接、创建statement等繁杂的过程。

mybatis通过xml或注解的方式将要执行的各种 statement配 置起来,并通过java对象和statement中sql的动态参数进行 映射生成最终执行的sql语句。

最后mybatis框架执行sql并将结果映射为java对象并返回。采 用ORM思想解决了实体和数据库映射的问题,对jdbc 进行了 封装,屏蔽了jdbc api 底层访问细节,使我们不用与jdbc api 打交道,就可以完成对数据库的持久化操作 。

二、MyBatis传统开发步骤

首先,我们可以先访问一下MyBatis官网地址:http://www.mybatis.org/mybatis-3/,这里有完整的mybatis的介绍。

2.1 添加MyBatis的坐标

把mysql和mybatis的坐标引入pom.xml中。

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.32</version>
</dependency>
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.7</version>
</dependency>

2.2 创建一个实体

在项目下创建一个User.java的实体。

public class User {
    private int id;
    private String username;
    private String password;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

2.3 编写映射文件

在文件夹resources下再创建一个mapper文件夹,再创建映射文件UserMapper.xml。后续我们的sql语句可以全部写到这里。

2.3.1先写一个通用的dtd约束头

<?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">

2.3.2 再配置mapper

这里是select子句,当然也可以时insert、update等等。

<mapper namespace="userMapper">
    <select id="findAll" resultType="user">
        select * from db1.user
    </select>
</mapper>
  • namespace:命名空间。起名可以随意。例如使用时我们可以用userMapper.findAll来使用对应的select语句。

  • resultType:结果类型。从数据库查询到的数据封装到哪个位置。例如我们这里的select子句查询到的结果要封装到User实体集中,但是这里用user而不适用domain.User是因为在接下来的核心配置文件SqlMapConfig.xml中我们通过typeAliases标签将domain.User更名为user。

注意:这里必须先要有一个user数据库表。

2.4 编写核心文件

2.4.1 核心配置文件SqlMapConfig.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!--通过properties标签加载外部properties文件-->
    <properties resource="jdbc.properties"/>
    <!--自定义别名-->
    <typeAliases>
        <typeAlias type="domain.User" alias="user"/>
    </typeAliases>
    <!--数据源环境-->
    <environments default="developement">
        <environment id="developement">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    <!--加载映射文件-->
    <mappers>
        <mapper resource="mapper/UserMapper.xml"/>
    </mappers>
</configuration>
  • typeAliases:设置类型别名。比如这里我们使用自己定义的user更换本来的domain.User。所以在UserMapper.xml中我们就可以把sql语句中的resultType字段写成“user”。但是mybatis本身也为我们提供了一些别名来方便简写,如下:

别名

数据类型

string

java.lang.String

long

java.lang.Long

java

java.lang.Integer

double

java.lang.Double

boolean

java.lang.Boolean

而后期我们在执行更新操作时,就可以直接使用parameterType="int" 而不是 parameterType="java.lang.Integer",比如:

<update id="update" parameterType="int">
update user set username=#{username},password=#{password} where id=#{id}
</update>
  • transactionManager:事务管理器。取值有两种,JDBC和MANAGED,这里我们使用JDBC。

  • dataSource:数据源。取值有三种,UNPOOLED、POOLED和JNDI,这里我们使用POOLED,利用“池”的概念将 JDBC 连接对象组织起来。

  • property:配置数据库连接池的属性。这里使用了jdbc.properties来简化书写,当然也可以直接写。

  • mappers:用来加载映射,加载方式有如下几种:

• 使用相对于类路径的资源引用,例如:

<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>

• 使用完全限定资源定位符(URL),例如:

<mapper url="file:///var/mappers/AuthorMapper.xml"/>

• 使用映射器接口实现类的完全限定类名,例如:

<mapper class="org.mybatis.builder.AuthorMapper"/>

• 将包内的映射器接口实现全部注册为映射器,例如:

<package name="org.mybatis.builder"/>

2.4.2 配置文件jdbc.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/db1
jdbc.username=root
jdbc.password=root

2.5 测试

2.5.1 编写测试代码

/**
 * 查询
 * @throws IOException
 */
@Test
public void test1() throws IOException {
    //获得核心配置文件
    InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
    //获得session工厂对象
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
    //获得session会话对象
    SqlSession sqlSession = sqlSessionFactory.openSession();
    //执行操作 参数:namespace+id
    List<User> userList = sqlSession.selectList("userMapper.findAll");
    //打印数据
    System.out.println(userList);
    //释放资源
    sqlSession.close();
}
  • SqlSessionFactoryBuilder :工厂构建器。通过加载mybatis的核心文件的输入流的形式构建一个SqlSessionFactory对象 。

  • SqlSessionFactory:工厂对象 ,用来创建sql会话。openSession( )会默认开启一个事务,但事务不会自动提交,也就意味着需要手动提 交该事务,更新操作数据才会持久化到数据库中 。如果里面传一个参数为true,那么不需要手动提交事务(更新操作中sqlSession.commit()方法就不需要写了)。

  • SqlSession :会话对象。执行接下来的增删改查操作。

2.5.2 代码要点

这里我们可以看到,查询数据的一段java代码为:

List<User> userList = sqlSession.selectList("userMapper.findAll");

而这句代码中sqlSession.selectList的参数即我们刚才在UserMapper.xml 中写的代码:

<mapper namespace="userMapper">
    <select id="findAll" resultType="user">
        select * from db1.user
    </select>
</mapper>

同理,我们也可以同样得到添加数据、修改数据和删除数据类似的代码:

  • 添加数据:

sqlSession.insert("userMapper.add", user);
<insert id="add" parameterType="快速入门.User">
insert into user values(#{id},#{username},#{password})
</insert>
  • 修改数据

sqlSession.update("userMapper.update", user);
<update id="update" parameterType="快速入门.User">
update user set username=#{username},password=#{password} where id=#{id}
</update>
  • 删除数据

sqlSession.delete("userMapper.delete",3);
<delete id="delete" parameterType="快速入门.User">
delete from user where id=#{id}
</delete>

2.5.3 输出结果

执行编写好的代码,可以看到输出结果:

上面被选中的输出语句为:

[User{id=1, username='zhangsan', password='123'}, User{id=2, username='lisi', password='234'}, User{id=5, username='wangwu', password='abc'}, User{id=6, username='ray', password='111'}]

而我们再看一下数据库当中的数据,判断是否输出正常:

这里我们可以看到,一共4条数据,数据库中的数据已经被我们成功查找到。

三、总结

原来直接使用JDBC的sql代码被我们写入到了映射文件UserMapper.xml中,后续一些动态sql的加入更加简化了xml中代码量的书写。

而在Java代码中,我们只需要新建一些SqlSession对象便可以将xml中的sql语句直接使用。耦合度大大降低

但是我们也不难发现,这样的配置还是相对复杂的,因此就有了后来的MyBatisPlus来更加简化我们的代码书写。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

什么是MyBatis 的相关文章

  • 使用祖父母接口的默认方法

    我完全不明白为什么这行不通 interface Test default void doMagic System out println Abracadabra class TestImpl implements Test class Sp
  • 构建 jar 后无法运行 exe

    我制作了一个简单的实用应用程序 其中我有一个要运行的exe文件 我通过使用它来运行 Runtime getRuntime exec this getClass getResource filename exe getPath 当我从 ide
  • java IO将一个文件复制到另一个文件

    我有两个 Java io File 对象 file1 和 file2 我想将 file1 的内容复制到 file2 有没有一种标准方法可以做到这一点 而无需我创建一个读取 file1 并写入 file2 的方法 不 没有内置方法可以做到这一
  • 使用 python 中的 java 库

    我有一个 python 应用程序和 java 应用程序 python 应用程序为 java 应用程序生成输入并在命令行上调用它 我确信一定有一个更优雅的解决方案 就像使用 JNI 从 Java 调用 C 代码一样 有什么指点吗 仅供参考 我
  • spring启动时如何加载@Cache?

    我正在使用 spring cache 来改进数据库查询 其工作原理如下 Bean public CacheManager cacheManager return new ConcurrentMapCacheManager books Cac
  • 运行Java程序时出错

    我正在尝试使用 netbeans 运行我的 java 程序 但收到此错误 有什么建议吗 Exception in thread AWT EventQueue 0 java lang NullPointerException at javax
  • 获取运行时提供的类名的 n 维数组的类

    给定一个完全限定的类名和多个维度 我想获取该类的类名 我相信我可以这样做 public Class elementType Class forName className return Array newInstance elementTy
  • 想要从 beanIO 字段名称标签在 csv 中写入标题

    我想在 csv 文件中写入标题 因为我的文本文件不包含任何标题 所以我想从 beanIO 字段名称标签写入它 我有一个 beanIO 有两个流 一个用于读取 另一个用于写入 这是输入文件 文本输入 txt 1 约翰 露 BA xxx1萨姆
  • Spring Boot,使用 EhCache 进行缓存

    我需要在我的应用程序中缓存一些数据 我正在考虑使用 Ehcache 我有几个问题 Ehcache需要另外一台服务器吗 我需要其他客户端来使用 Ehcache 吗 Ehcache 如何与多个实例配合使用 是否有可能使用 Ehcache 创建类
  • 如何从 Java 类调用 Kotlin 类

    我需要将意图从 java 活动传递到 Kotlin 活动 Java活动ProfileActivity class Intent selectGameIntent new Intent ProfileActivity this kotlin
  • 如何告诉杰克逊在反序列化期间忽略空对象?

    在反序列化过程中 据我理解是将JSON数据转换为Java对象的过程 我如何告诉Jackson 当它读取不包含数据的对象时 应该忽略它 我正在使用 Jackson 2 6 6 和 Spring 4 2 6 我的控制器收到的JSON数据如下 i
  • 如何将捕获的图像写入/粘贴到文档文件?

    我有一个场景 我需要捕获图像并将它们一个接一个地写入到一个word文件中 我已经编写了下面的代码 但似乎不起作用 请帮忙 Robot robot try robot new Robot BufferedImage screenShot ro
  • 定时器启动/停止参数

    自从加入这个社区以来 我在技能和进步方面取得了突飞猛进的进步 你们都是一个巨大的帮助 我无法提供一个计时器 该计时器已在启动和停止时实现了某些参数 我要么收到错误消息 局部变量计时器可能尚未初始化 要么没有收到错误消息 但什么也没有发生 也
  • jstack 是否停止在较新的 JDK8 版本上工作?

    我惊讶地发现 不知何故 最近 jstack 停止了在较新的 JDK 8 上的工作 我不确定这发生在哪个版本 但我确实得到 36649 Unable to open socket file target process not respond
  • Android 布局崩溃

    I use a XWalkView https crosswalk project org 加载网页和视频查看器 https github com Bilibili ijkplayer在我的应用程序中播放实时视频 我希望 IjkVideoV
  • Java 统一编码

    A Java char is 2 bytes http java sun com docs books tutorial java nutsandbolts datatypes html 最大大小为 65 536 但有95 221 http
  • 如何提高QNX6下Eclipse IDE的性能

    我们在 VMWare 环境中通过 QNX6 运行 Eclipse 速度非常慢 Eclipse 是这样启动的 usr qnx630 host qnx6 x86 usr qde eclipse eclipse data root workspa
  • 确定方法调用顺序的接口设计模式

    我想创建一个具有多种方法的 Java 接口 但我希望界面的用户只能按照我定义的顺序或顺序调用方法 例如buyTicket 不应在此之前调用reserveTicket 问 有没有设计模式或任何关于如何做到这一点的提示 我考虑过 A 接口被包装
  • 在 Eclipse Testrunner 中使用名称的 ParameterizedTest

    当您使用 Eclipse TestRunner 运行 JUnit 4 ParameterizedTest 时 图形表示相当愚蠢 对于每个测试 您都有一个名为 0 1 ETC 是否可以进行测试 0 1 等显式名称 实施一个toString测试
  • 我可以在方法体内使用注释吗?

    允许 Java 注释的语义将它们放置在某处在函数体内 例如注释特定的函数调用 语句或表达式 例如 class MyClass void theFunc Thing thing String s null Catching NullPoint

随机推荐

  • SpringBoot整合RabbitMQ

    该篇文章内容较多 包括有rabbitMq相关的一些简单理论介绍 provider消息推送实例 consumer消息消费实例 Direct Topic Fanout的使用 消息回调 手动确认等 但是关于rabbitMq的安装 就不介绍了 在安
  • ElasticSearch第七讲 ES查询速度为什么那么快

    介绍给大家一个开源SpringCloud项目 整合了大部分开源中间件 详情信息可以查看文档 spring cloud开源组件开发 另外自己以后博客所讲解的代码内容 都会我的Git上同步 GitHub同步 GIT地址 ES使用的数据结构是倒排
  • Git基础(常用命令)介绍

    版本控制是一种记录若干文件内容变化 以便将来查阅特定版本修订情况的系统 关于版本控制分为三种 本地版本控制系统 如rcs 集中化的版本控制系统 如CVS SVN 分布式版本控制系统 如Git Git基础要点 Git和其它版本控制系统的主要差
  • 【华为OD机试】乱序整数序列两数之和绝对值最小【2023 B卷

    华为OD机试 真题 点这里 华为OD机试 真题考点分类 点这里 题目描述 给定一个随机的整数 可能存在正整数和负整数 数组 nums 请你在该数组中找出两个数 其和的绝对值 nums x nums y 为最小值 并返回这个两个数 按从小到大
  • 安卓开发--应用市场的界面制作(一)--viewpager+fragment实现可滑动的底部导航栏

    相关文章 前言 布局文件 MainAcivity 细节 相关文章 Android Fragment完全解析 关于碎片你所需知道的一切 这是一片很不错的博文 基本上看完就懂fragment是个什么情况了 ViewPager防止Fragment
  • 什么是智慧矿山解决方案发展方向?企业又该怎么做呢?

    什么是智慧矿山呢 智慧矿山是指采用现代高新技术和全套矿山自动化设备等等一些新兴的技术来提高矿山的生产效率和经济效益 通过对矿山生产过程进行实时动态监控 通过这些措施能够让矿山生产维持在最佳状态和最优水平 新型数字化技术能够帮助传统矿业在生产
  • STM32 PWM输出

    STM32 PWM输出 工作过程 我们假定定时器工作在向上计数PWM 模式 且当 CNT
  • 天梯赛座位分配PTA

    天梯赛座位分配PTA 天梯赛座位分配PTA TOC 前言 PTA的一道题目 一 题目内容 题目 天梯赛每年有大量参赛队员 要保证同一所学校的所有队员都不能相邻 分配座位就成为一件比较麻烦的事情 为此我们制定如下策略 假设某赛场有 N 所学校
  • QT学习_02_Lambda表达式——槽函数的正确打开方式

    1 带参数的信号 假设发送的信号带参数 信号是可以重载的 我用同一个函数名称 一个带参数 一个不带参数 在点击 切换到主窗口 按钮的时候 同时发射这两个信号 subwidget h ifndef SUBWIDGET H define SUB
  • ubuntu学习笔记

    ubuntu学习笔记 前言 一 ubuntu 22 04 更换阿里源 二 ubuntu22 04安装搜狗输入法 三 linux系统分区 个人向 四 vi及vim文本编辑器使用 五 nano文本编辑器使用 六 查看IP及网关DNS并设置IP地
  • 第09课:生活中的工厂模式——你要拿铁还是摩卡

    用程序来模拟生活 从剧情中思考工厂模式 工厂模式的模型抽象 类图 模型说明 简单工厂的优点 简单工厂的缺点 模型的拓展应用 应用场景 拓展 工厂三姐妹 简单工厂模式 工厂方法模式 抽象工厂模式 进一步思考
  • 遇到问题--Nginx---tomcat启动web程序访问静态资源时404找不到

    http blog csdn net zzq900503 article details 76927074 给web站点配置域名转发后 tomcat启动web程序访问静态资源时404找不到 经过确认项目资源路径都没问题 后来经过排查后发现是
  • 配置samba服务

    什么是samba服务 是 和windows 进行 文件打印机共享的组件 结果就是linux windows 之间可以互相访问它们的共享文件 说明 我用的是ubuntu系统 ubuntu系统安装samba服务 确定自己是否安装samba dp
  • (一)Google发布了一个新的Tensorflow物体识别API

    做图像识别有很多不同的途径 谷歌最近发布了一个使用Tensorflow的物体识别API 让计算机视觉在各方面都更进了一步 这篇文章将带你测试这个新的API 并且把它应用在youtube上 可以在GitHub上获取用到的全部代码 https
  • JDBC连接数据库URL示例

    jdbc mysql localhost 3306 crm useSSL false useUnicode true characterEncoding UTF 8
  • matlab扩充内存,matlab中内存不够用的解决方案

    1 在命令行中输入pack函数来整理内存 pack函数到底是什么机制呢 这里参考了MATLAB的help文档 话说回来 help始终是学习MATLAB的 金参考标准 用法 pack pack filename pack filename 第
  • Struts配置文件详解

    Struts1配置文件
  • 最好的工程师像投资者一样思考,而不是建设者

    我在大学期间住在图书馆 我学习的教科书理论越多 我就会成为一名更好的工程师 我想 然而 当我开始工作时 我注意到业内最优秀的工程师并不一定比应届毕业生了解更多的理论 他们只是带来了不同的心态 即投资者的心态 正是这种心态帮助他们提出更聪明的
  • 谈一谈,自身对技术经理这个职位的理解吧

    前言 19年初在上一家公司离职 在上一公司服役了4年半 成长了不少 收获了不少东西 在上一公司也带过很多团队 多的时候6 7个人 少的时候2人 也总结了很多的所谓的经验吧 由于一系列原因吧 离职来到了我现在的公司 岗位职责 到这边以后 入职
  • 什么是MyBatis

    一 MyBatis概述 1 1 原始的JDBC操作 谈及mybatis 必然需要先了解Java和数据库的连接技术 JDBC Java DataBase Connectivity 但是原始JDBC操作中 却存在如下缺点 数据库连接创建 释放频