首页 > 其他分享 >一文教你如何手写一个mybatis自定义框架

一文教你如何手写一个mybatis自定义框架

时间:2024-06-12 09:29:00浏览次数:19  
标签:自定义 框架 数据库 user sql mybatis 手写 id

 本文主要介绍原始jdbc操作有哪些弊端等方面说明持久层框架出现的原因,另一方面介绍如何自己仿写一个mybatis框架。学习完本文相信你对日常使用的mybatis框架有更深的理解!

简介

说到持久层框架,我们很快能想到hibernate、mybatis。Hibernate是全自动的持久层框架,而mybatis则是半自动的。那么两者有何区别?下面先简单认识一下这两个框架的异同,以便更好的理解下面阐述的自定义持久层框架的设计思想,毕竟下面的自定义框架实际就是通过阅读mybatis源码,取其核心设计,去掉细枝旁叶而设计的一个半自动持久层框架。

ORM全称Object/Relation Mapping:表示对象-关系映射的缩写。

Hibernate:全自动的持久层ORM框架。Hibernate是一个开源的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO(Plain Ordinary Java Object)与数据库表建立映射关系,是一个全自动的ORM框架,hibernate可以自动生成SQL语句,自动执行,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。

Mybatis:MyBatis 是一款优秀的半自动持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO为数据库中的记录。

使用 Hibernate 查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。而 MyBatis 在查询关联对象或关联集合对象时,需要手动编写 sql 来完成,所以,称之为半自动 ORM 映射工具。

既然无论是全自动的hibernate,或是半自动的mybatis,其本质都是对JDBC进行了封装,使Java程序员可以使用对象编程思维来操纵数据库。

下面我们不妨看看使用JDBC编程是怎样的,直接使用JDBC编程会有什么问题,找到问题,解决问题,然后提出针对问题的解决方案。

jdbc操作存在的问题

一个使用原始jdbc对数据进行查询的案例

package com.kmning.wallet.jdbc;

import com.kmning.wallet.jdbc.pojo.User;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @author kangming.ning
 * @date 2021/5/2 9:16
 */
public class JdbcQueryDemo {
    public static void main(String[] args) {
        Connection connection=null;
        PreparedStatement preparedStatement=null;
        ResultSet resultSet =null;
        try {
            //加载数据库驱动
            //Class.forName("com.mysql.jdbc.Driver");
            //过驱动管理类获取数据库链接
            connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/yourdb?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai", "root", "root");
            //编写sql语句
            String sql="select * from user where username=? or telphone=?";
            //获取预处理statement
             preparedStatement = connection.prepareStatement(sql);
            //设置参数,第一个参数为sql语句中参数的序号(从1开始),第二个参数为设置的参数值
             preparedStatement.setString(1,"aa");
             preparedStatement.setString(2,"666");
            //向数据库发出sql执行查询,查询出结果集
            resultSet = preparedStatement.executeQuery();
            //遍历结果集,封装数据
            List<User> userList=new ArrayList<>(10);
            while (resultSet.next()){
                int id = resultSet.getInt("id");
                String username = resultSet.getString("username");
                String telphone = resultSet.getString("telphone");
                //封装结果集
                User user = new User();
                user.setId(id);
                user.setUsername(username);
                user.setTelphone(telphone);
                userList.add(user);
            }
            System.out.println(userList);

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            //释放资源
            if (resultSet!=null){
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (preparedStatement!=null){
                try {
                    preparedStatement.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (connection!=null){
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}
​代码非常简单且常规,JDBC操作无非都类似于上面的套路。通过驱动获取数据库连接,通过PreparedStatement预编译SQL语句,设置参数,然后向数据库发出sql执行查询,查询出结果集,遍历结果集,将结果集封装到POJO对象集合。当然,最后还得将相关资源释放。

但在实际的企业应用中,数据库的表少则几十个,多则几百个,如果使用类似于上述的方式去操作数据库,不仅前期开发工作巨大,而且后期的维护也将是一场灾难。那么上述代码存在哪些问题?让我们带着疑问对代码进行分析,然后找出问题所在,然后找到解决方案去解决它们。

以上代码存在的问题:

  • 数据库配置信息存在硬编码

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

  • Sql语句在代码中硬编码,造成代码不易维护,实际应用中sql变化的可能较大,sql变动需要改变java代码

  • 使用preparedStatement向占位符号传参数存在硬编码,因为sql语句的where条件不一定,可能多也可能少,修改sql还要修改代码,系统不易维护

  • 对结果集解析存在硬编码(查询列名),sql变化导致解析代码变化,系统不易维护,如果能将数据库记录封装成pojo对象解析比较方便

解决思路:

  • 数据库配置信息提供配置文件,避免改动连接等配置信息需要重新编译代码

  • 使用数据库连接池初始化连接资源

  • 将sql语句、设置参数、获取结果集参数抽取到xml配置文件中

  • 使用反射、内省等底层技术,自动将实体与表进行属性与字段的自动映射

问题找到了,也整理出了解决思路,那么就可以着手设计框架了。

自定义mybatis框架

我们整理出了解决思路,接下来需要编写一个通用的解决方案,也就是框架,去解决问题。下面我们整理一下实现这样一个框架需要去做哪些工作。

首先是自定义框架肯定是独立的一个jar,然后提供给客户端使用。我们可以将开发工作分为两部分,一是框架需要做哪些东西,二是使用端(项目)需要做哪些东西。为了描述与理解方便,下面称框架端为mybatis-custom框架。

mybatis-custom框架负责对jdbc进行封装,提供基本操作接口,并对结果集和pojo实体进行映射,而客户端(项目)则需要提供数据库配置信息、sql配置信息(如UserMapper.xml)。使用端提供xxMapper.xml,意味着对sql的编写的控制权还是属于用户的(半自动映射框架)。

使用端

提供两部分配置信息:一是数据库配置信息。二是sql mapper配置信息,mapper文件定义了sql语句、参数类型、返回值类型、结果返回类型等信息。

使用配置文件来提供这两部分配置信息

  • sqlMapConfig.xml:存放数据库配置信息、同时存放mapper.xml的全路径(这样在方便在解析sqlMapConfig时直接解析mapper.xml,相关信息保存到Configuration)。样例如下

    <configuration>
            <!--数据库配置信息-->
        <dataSource>
            <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
            <property name="jdbcUrl" value="jdbc:mysql:///yourdb?serverTimezone=Asia/Shanghai"></property>
            <property name="username" value="root"></property>
            <property name="password" value="root"></property>
        </dataSource>
    ​
        <!--存放mapper.xml的全路径-->
        <mapper resource="UserMapper.xml"></mapper>
        <mapper resource="ProductMapper.xml"></mapper>
    ​
    </configuration>

  • mapper.xml:存放sql配置信息。样例如下

    <mapper namespace="com.kmning.mybatis.test.dao.UserDao">
    ​
        <!--sql的唯一标识:namespace.id来组成 : statementId-->
        <select id="findAll" resultType="com.kmning.mybatis.test.pojo.User" >
            select * from user
        </select>
        <select id="findByCondition" resultType="com.kmning.mybatis.test.pojo.User" parameterType="com.kmning.mybatis.test.pojo.User">
            select * from user where id = #{id} and username = #{username}
        </select>
    ​
        <update id="updateUserById" resultType="java.lang.Integer" parameterType="com.kmning.mybatis.test.pojo.User">
            UPDATE `user` SET username=#{username},telphone=#{telphone} WHERE id=#{id};
        </update>
    ​
        <insert id="insertUser" resultType="java.lang.Integer" parameterType="com.kmning.mybatis.test.pojo.User">
            INSERT INTO `user` VALUES(#{id},#{username},#{telphone});
        </insert>
    ​
        <delete id="deleteUserById" resultType="java.lang.Integer" parameterType="com.kmning.mybatis.test.pojo.User">
            DELETE FROM `user` WHERE id=#{id};
        </delete>
    </mapper>

自定义持久层框架端

创建框架工程,引入相关maven依赖,根据上面的分析,框架需要解析xml,用连接池解决连接创建关闭频繁问题,那么引入相关依赖如下

<dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6.1</version>
        </dependency>
        <dependency>
            <groupId>jaxen</groupId>
            <artifactId>jaxen</artifactId>
            <version>1.2.0</version>
        </dependency>
        <dependency>
            <groupId>mysql

标签:自定义,框架,数据库,user,sql,mybatis,手写,id
From: https://blog.csdn.net/u012882823/article/details/139614342

相关文章

  • 10 种超赞的 MyBatis 写法!
    https://mp.weixin.qq.com/s/U3m2iLfujYLy5T-B2OI3ZA MyBatis虽说给我们的开发带来了很多的便捷,但有些地方写起来依旧比较的麻烦,比如配置XML的时候,但是一个好的写法,不仅能为我们节省不少时间、还能能降低出错的概率,下面就给大家分享一些优质的写法: 1、用来循环容器的标签fo......
  • 【数据库】mybatis生成java代码之AutoGenerator配置
    哈喽,大家好,我是木头左,AI改变生活!本文将详细解释MyBatis生成Java代码的过程,包括全局配置、数据源配置和策略配置。1.全局配置首先,我们需要创建一个GlobalConfig对象,用于配置MyBatis的全局设置。以下是一些常用的全局配置选项:setOutputDir(StringoutputDir):设置生......
  • electron + vue3 自定义窗口:移动,缩放,置顶
    electronmain.jsconst{BrowserWindow,ipcMain}=require('electron');constpath=require("path")constCustomWindow=require('./CustomWindow')constwin=newBrowserWindow({frame:false,transparent:true,......
  • mybatis条件判断及动态sql的简单拓展
    在MyBatis中,可以通过使用一些特定的标签(、...)以及其他动态SQL功能来实现条件判断。这使得SQL查询可以根据不同的条件动态生成,从而提高查询的灵活性和可维护性。本文以订单列表简单查询为例,对mybatis条件判断及动态sql进行简单拓展。建表语句CREATETABLE`wwtms`.`order_t......
  • 利用自定义标签,实现select下拉列表默认选中
    //创建块函数方法,用于替换文本中的值functionsmarty_block_get_cates($params,$content,&$_sm,&$repeat){if(!$repeat){$ci=&get_instance();$cates=$ci->db->get('category')->result_array();$cates=get_dat......
  • SpringBoot3.0.x适配mybatis版本
    SpringBoot适配mybatis版本最低为3.0.3<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>3.0.3</version><......
  • python绘制词云图最全教程,查看文章关键词,自定义词云图形状等,看完就会
    ......
  • Java (MyBatis-Plus 项目)
    前沿MyBatis-Plus在使用这个时候的它通过提供简洁、强大的API和注解支持,简化了常见的数据库操作。以下是关于MyBatis-Plus中注解的解释和示例,理解和使用1.实体类注解@TableName:用于指定数据库表的名称。@TableId:用于指定主键字段。@TableField:用于指定非主键字段......
  • VsCode中snippets --- vue自定义代码片段
    vue自定义代码片段Vue2代码片段1、点击文件→首选项→选择配置用户代码片段2、在弹出这个窗口中选择新建全局代码片段文件3、选择后在此处输入文件名后按‘Enter’键确定4、点击确定后会生成以下文件5、替换成以下vue2代码片段6、使用代码片段Vue3代码片段使用defineC......
  • Springboot + Mybatis Plus整合Sqlite3
    什么是Sqlite3sqlite3是一个进程内的库,实现了自给自足、无服务器、零配置、事务性的SQL数据库引擎。它是一个增长最快的数据库引擎。它不是一个独立的进程,可以按应用程序需求进行静态或动态连接,SQLite直接访问其存储文件。为什么要使用Sqlite3不需要一个单独的服务器进程......