zoukankan      html  css  js  c++  java
  • 浅谈mybatis如何半自动化解耦

           在JAVA发展过程中,涌现出一系列的ORM框架,JPA,Hibernate,Mybatis和Spring jdbc,本系列,将来研究Mybatis。

          

          通过研究mybatis源码,可将mybatis的大致架构总结为下图:

          1.根据Mybatis源码,将其抽象为三层:基础支持层,核心处理层和接口层

          2.基础支持层包括:数据源、事务管理、日志、类型转换、缓存、Bind、解析器等

          3.核心处理层包括:配置解析、配置映射、SQL解析、SQL执行、结果集映射、插件等

          4.接口层主要提供JAVA API

          

           在本篇文章中,将基于该框架图,解决如下几个问题:

           Q1:结合代码解析mybatis的CRUD原理是怎样的?

           Q2:为什么半自动化的Mybatis比自动化的Hibernate受欢迎?

           Q3:Mybatis为什么能实现松耦合?

    一  mybatis的CRUD原理


      为了解决该问题,我们先来看看如下代码:

      该代码实现的功能是:根据user_id查询用户信息。  从代码中,我们可以看出,大致分为五步:

      第一步:读取mybatis的全局配置文件mybatis-config.xml内容

      第二步:创建SqlSessionFactory会话工厂

      第三步:根据SqlSessionFactory创建SQL会话SqlSession

      第四步:执行查询操作

       public static void main(String[] args) throws IOException {
            //读取配置文件内容
            String resource = "demo/mybatis/resources/mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            //创建SqlSessionFactory
            SqlSessionFactory sqlSF = new SqlSessionFactoryBuilder().build(inputStream);
            //创建SqlSession
            SqlSession sqlS = sqlSF.openSession();
    
            //根据id查询
            try {
                //查询user_id=2的记录
                List<UserInfo> list = sqlS.selectList("getUserInfoById", 2);
                for (UserInfo user : list) {
                    System.out.println("UserName:" + user.getUser_name() + ",Addr:" + user.getUser_addr());
                }
            } finally {
                sqlS.close();
            }
        }

     那么,我们再来看看,Mybatis-config.xml内容:

      从内容中,可以看出<configuration>下面有三个子节点,<properties>,<environment>和<mapper>节点。

    那么,这三个节点到底是表示什么呢?

    1.properties节点表示属性节点,可用于动态从外部获取资源,将获取的资源供上下文使用,我们来看看jdbc.properties内容

    #mysql
    driver=com.mysql.jdbc.Driver
    url=jdbc:mysql://127.0.0.1:3306/db_test?characterEncoding=UTF-8
    username=root
    password=root

    一看便知,这是访问数据库相关参数,那么哪个地方引用这些参数呢?<environment>子节点。

    2.environment节点,环境节点配置节点,如用于配置数据库测试环境,开发环境等,很容易看出dataSource的相关子节点的占位符就引用了

    properties节点从jdbc.properties获取的内容。

    3.mapper节点,即映射节点,用来链接映射文件,我们来看看该映射文件内容:

    <?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">
    
    <mapper namespace="mybatisEntity">
        <!--Query all-->
        <select id="listUserInfo" resultType="demo.mybatis.entity.UserInfo">
            SELECT user_name ,user_addr FROM user_info
        </select>
        <!--Query by id-->
        <select id="getUserInfoById" resultType="demo.mybatis.entity.UserInfo">
            SELECT user_name ,user_addr FROM user_info WHERE user_id=#{user_id}
        </select>
    
        <!--add-->
        <select id="addUserInfo" resultType="demo.mybatis.entity.UserInfo">
            INSERT INTO user_info(user_name,user_addr)VALUES(#{user_name},#{user_addr})
        </select>
    
        <!--delete-->
        <select id="delUserInfoById" resultType="demo.mybatis.entity.UserInfo">
            DELETE FROM user_info WHERE user_id=#{user_id}
        </select>
    </mapper>

    显而易见,这就SQL的增删改查。

          通过如上分析,我们在文章开始提出的三个问题,现在基本可以解决了。

    Q3:Mybatis为什么能实现松耦合?

           从如上分析,我们知道,使用mybatis作为ORM框架开发时,我们的SQL语句都写在xml配置文件中(如上文的userInfo-config.xml),从而解决了传统硬编码的

    强耦合问题,巧妙地实现了从“硬编码”到“软编码”的过程。

          除了松耦合的好处之外,有经验的开发人员应该清楚,硬编码存在一个重大问题,即当改变SQL代码后,需要重新编译、打包、部署等后,程序方可运行起来,

    而通过可配置化的xml方式实现的SQL语句,却不需要。

    Q4:为什么半自动化的Mybatis比自动化的Hibernate受欢迎?

          从功能上讲,Hibernate是非常强大的,但其有存在一些比较难以解决的问题:

          (1)学习成本大。对于新手,学习Hibernate的时间成本比Mybatis大很多,Mybatis很快就上手了

          (2)笨重。Hibernate强大的另一面,折射出其笨重的一面

          (3)封装SQL。Hibernate封装SQL,只向用户提供API接口,是造成其不灵活的根本因素

    然而,mybatis却将SQL独立出来,让用户自定义。

    通过如上对比,之所以说Hibernate自动化,因为SQL生成,解析,执行等都是由Hibernate自动生成的;

    之所以说Mybatis半自动化,是因为SQL语句需要用户自定义,SQL的解析,执行等工作由Mybatis执行。

    可以这么说,传统的jdbc是手工的,Hibernate是自动化的,而Mybati是基于jdbc和Hibernate的半自动化ORM框架。

    二  完整Mybatis CRUD


     (一)创建Web Application项目

    打开Intellij IDEA=>Create New Project=>Java Enterprise=>勾选 Web Application=>Next=>

    给项目命名MybatisCRUD=>Finish 

    (二)导入jar包

    这里主要导入两个jar包:MySQL驱动jar包和Mybatis jar包

    Project Structure(Ctrl+Alt+Shift+S)=>Modules=>MybatisCRUD=>Dependencies=>选择 JARS or  directories...

    成功导入后的结构如下:

     (三)创建测试数据

    #创建数据库
    DROP DATABASE IF EXISTS db_test
    CREATE DATABASE db_test
    
    #创建数据表
    DROP TABLE IF EXISTS User_Info
    
    CREATE TABLE user_info
    (
       user_id INT(5) AUTO_INCREMENT PRIMARY KEY NOT NULL,#用户id
         user_name VARCHAR(50) NOT NULL,#用户名
         user_addr VARCHAR(100) NOT NULL #地址
    )
    
    #插入模拟数据
    INSERT INTO user_Info(user_name,user_addr)
    VALUES('A','SH-PuDong'),('B','SH-YangPu'),
    ('C','SH-QingPu'),('D','SH-XuHui')

    (四)创建UserInfo实体

    package demo.mybatis.entity;
    
    public class UserInfo {
        String user_name;
        String user_addr;
    
        public String getUser_name() {
            return user_name;
        }
    
        public void setUser_name(String user_name) {
            this.user_name = user_name;
        }
    
        public String getUser_addr() {
            return user_addr;
        }
    
        public void setUser_addr(String user_addr) {
            this.user_addr = user_addr;
        }
    }
    View Code

    (五)创建三个资源文件

    1.jdbc.property

    #mysql
    driver=com.mysql.jdbc.Driver
    url=jdbc:mysql://127.0.0.1:3306/db_test?characterEncoding=UTF-8
    username=root
    password=root

    2.mybatis-config.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 resource="demo/mybatis/resources/jdbc.properties">
        </properties>
    
        <!--环境-->
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <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="demo/mybatis/resources/userInfo-config.xml"/>
        </mappers>
    </configuration>
    View Code

    3.userInfo.config.xml    

    <?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">
    
    <mapper namespace="mybatisEntity">
        <!--无条件查询-->
        <select id="listUserInfo" resultType="demo.mybatis.entity.UserInfo">
            SELECT user_name ,user_addr FROM user_info
        </select>
        <!--通过id查询-->
        <select id="getUserInfoById" resultType="myUserInfo">
            SELECT user_name ,user_addr FROM user_info WHERE user_id=#{user_id}
        </select>
    
        <!--add-->
        <insert id="addUserInfo">
            INSERT INTO user_info(user_name,user_addr)VALUES(#{user_name},#{user_addr})
        </insert>
    
        <!--delete-->
        <delete id="delUserInfoById">
            DELETE FROM user_info WHERE user_id=#{user_id}
        </delete>
    </mapper>
    View Code

    (六)CRUD

    1.查询  

    package demo.mybatis.Test;
    
    import demo.mybatis.entity.UserInfo;
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    
    public class TestMybatis {
        public static void main(String[] args) throws IOException {
            //读取配置文件内容
            String resource = "demo/mybatis/resources/mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            //创建SqlSessionFactory
            SqlSessionFactory sqlSF = new SqlSessionFactoryBuilder().build(inputStream);
            //创建SqlSession
            SqlSession sqlS = sqlSF.openSession();
    
            //根据id查询
            try {
                //查询user_id=2的记录
                List<UserInfo> list = sqlS.selectList("getUserInfoById", 2);
                for (UserInfo user : list) {
                    System.out.println("UserName:" + user.getUser_name() + ",Addr:" + user.getUser_addr());
                }
            } finally {
                sqlS.close();
            }
        }
    }
    View Code

    2.添加  

    package demo.mybatis.Test;
    
    import demo.mybatis.entity.UserInfo;
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    
    public class TestMybatis {
        public static void main(String[] args) throws IOException {
            //读取配置文件内容
            String resource = "demo/mybatis/resources/mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            //创建SqlSessionFactory
            SqlSessionFactory sqlSF = new SqlSessionFactoryBuilder().build(inputStream);
            //创建SqlSession
            SqlSession sqlS = sqlSF.openSession();
    
            //添加数据
            try{
                UserInfo addUser = new UserInfo();
                addUser.setUser_name("E");
                addUser.setUser_addr("BJ-DongCheng");
    
                sqlS.selectList("addUserInfo",addUser);
    
                List<UserInfo> list=sqlS.selectList("listUserInfo");
                for (UserInfo user :list){
                    System.out.println("UserName:"+user.getUser_name()+",Addr:"+user.getUser_addr());
                }
            }finally {
                sqlS.close();
            }
        }
    }
    View Code

    3.删除

    package demo.mybatis.Test;
    
    import demo.mybatis.entity.UserInfo;
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    
    public class TestMybatis {
        public static void main(String[] args) throws IOException {
            //读取配置文件内容
            String resource = "demo/mybatis/resources/mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            //创建SqlSessionFactory
            SqlSessionFactory sqlSF = new SqlSessionFactoryBuilder().build(inputStream);
            //创建SqlSession
            SqlSession sqlS = sqlSF.openSession();
    
            //删除
            try{
                sqlS.selectList("delUserInfoById",12);
    
                List<UserInfo> list=sqlS.selectList("listUserInfo");
                for (UserInfo user :list){
                    System.out.println("UserName:"+user.getUser_name()+",Addr:"+user.getUser_addr());
                }
            }finally {
                sqlS.close();
            }
        }
    }
    View Code

    (七)代码目录结构

     三  版权区


      感谢您的阅读,若有不足之处,欢迎指教,共同学习、共同进步。

      博主网址:http://www.cnblogs.com/wangjiming/。

      极少部分文章利用读书、参考、引用、抄袭、复制和粘贴等多种方式整合而成的,大部分为原创。

      如您喜欢,麻烦推荐一下;如您有新想法,欢迎提出,邮箱:2098469527@qq.com。

      可以转载该博客,但必须著名博客来源。

  • 相关阅读:
    mysql数据库常用指令
    解决windows的mysql无法启动 服务没有报告任何错误的经验。
    “Can't open file for writing”或“operation not permitted”的解决办法
    启动Apache出现错误Port 80 in use by "Unable to open process" with PID 4!
    如何打开windows的服务services.msc
    常见的HTTP状态码 404 500 301 200
    linux系统常用的重启、关机指令
    (wifi)wifi移植之命令行调试driver和supplicant
    linux(debian)安装USB无线网卡(tp-link TL-WN725N rtl8188eu )
    alloc_chrdev_region申请一个动态主设备号,并申请一系列次设备号
  • 原文地址:https://www.cnblogs.com/wangjiming/p/10384975.html
Copyright © 2011-2022 走看看