MyBatis-基础

定义

        MyBatis属于数据库相关的一个Java持久层框架,用于简化JDBC操作。  它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息, 只需要编写对应的接口类而不需要写实现类,就能够完成对数据库的CRUD操作。

        每个MyBatis应用程序主要都是使用SqlSessionFactory实例的,一个SqlSessionFactory实例可以通过SqlSessionFactoryBuilder获得。SqlSessionFactoryBuilder可以从一个xml配置文件或者一个预定义的配置类的实例获得。

优点

把sql语句提出到xml文件中,不再有Dao文件。

降低了java代码和sql语句的耦合度

MyBatis的基本配置

     MyBatis的基本配置流程如下:

1.导入JAR包

       使用MyBatis需要导入MyBatis和数据库驱动jar包,如下所示:

<!-- MyBatis jar包 -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.6</version>
</dependency>
<!-- mysql驱动jar包 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.48</version>
</dependency>

2.编写接口类

      只需要编写对应的接口类而不需要写实现类,就能够完成对数据库的CRUD操作。

3.编写接口类对应的Mapper映射器

        一个接口类对应一个Mapper的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">
 <!-- namespace: 命名空间 (内容为接口类的全名)每一个Mapper.java会有一个对应的Mapper.xml文件
 -->
<mapper namespace="xxx.xxxMapper">
    //...

</mapper>

4.编写MyBatis的配置文件

<?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>
    <!-- 用于控制台输出日志内容 -->
    <!-- <settings>
    <setting name="logImpl" value="STDOUT_LOGGING"></setting>
    </settings> -->
    <!-- environments标签内部可以配置多个environment,通过default选择出需要加载的一个数据库环境 -->
    <environments default="development">
        <!-- id值为development的开发环境 -->
        <environment id="development">
            <!-- 事务管理,使用JDBC管理 -->
            <transactionManager type="JDBC"/>
            <!-- 数据源,使用数据库连接池 -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mydb3?useUnicode=true;
                                                        characterEncoding=utf-8;useSSL=false"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
        <!-- 后面还可以配置多个environment -->
        <environment id="xxx">
            ...
        </environment>
    </environments>
  	
    <!-- 配置Mapper映射器的路径 -->
    <mappers>
        <mapper resource="mapper/xml/TClassMapper.xml"></mapper>
        <!-- 如果有多个mapper,则在后面继续添加对应的mapper -->
    </mappers>
</configuration>

配置详解如下:

mappers(引入映射器)

     常用的引入映射器方法有3种,如下所示:

  • 1.使用文件路径引入映射器
<mappers>
    <mapper resource="mapper/xml/TClassMapper.xml"></mapper>
</mappers>
  • 2.使用包名引入映射器
<mappers>
    <package resource="mapper.xml"></package >
</mappers>
  • 3.使用类注册引入映射器
<mappers>
    <class resource="mapper.xml.TClassMapper"></class >
</mappers>

MyBatis的组成

       MyBatis的组成如下所示:

        详解如下:

1.SqlSessionFactoryBuilder(构造器)

      根据配置信息或代码生成SqlSessionFactory接口。

2.SqlSessionFactory(工厂接口)

      MyBatis的应用都是以SqlSessionFactory的实例为中心,用来生成SqlSession

3.SqlSession(Sql处理器)

       SQLSession是一个接口类,类似于JDBC的Connection对象,有如下两种执行方法返回执行结果:

  • 获取Mapper接口类映射器

         让Mapper映射器通过命名空间和方法名称去找到对应的SQL,发送到数据库并执行,返回结果。

  • 直接执行SQL语句

   

    SqlSession支持事务,可以通过commit()和rollback()方法来提交或者回滚事务。      

4.Sql Mapper(映射规则及SQL定义)

        Sql Mapper即Mapper映射器,MyBatis的新设计组件,由Java接口和XML文件(或注解)构成,需要给出对应的SQL和映射规则。负责发送SQL去执行。并返回结果。

Mapper映射器配置

1.元素

       <mapper>里面有如下元素:

select

映射查询语句

最常用最复杂的元素。可以自定义参数,返回结果集等

update

映射更新语句

执行后返回一个整数,代表更新的条数。

delete

映射删除语句

执行后返回一个整数,代表删除的条数。

insert

映射插入语句

执行后返回一个整数,代表插入的条数。

sql 允许定义一部分的sql,然后可以在各个地方引用它
resultMap 用来描述从数据库中查询出来的结果集中来加载对象
cache 给命名空间缓存配置
cache-ref 其他命名空间缓存配置引用

2.元素的属性

id 唯一标识符,需要和Mapper接口类中对应的方法名一样
parameterType 传入参数类型
resultType

返回结果类型

如果返回结果是一个数字,则可以不用写

如果返回结果是一个实体类,则resultType="实体类名"

如果返回结果是一个List<T>集合,则resultType="T"

如果返回结果是一个Map集合,则resultType="map"

resultMap 外部resultMap的命名引用
timeout 这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。
fetchSize 影响驱动程序每次批量返回的结果行数。

Mapper的实现原理

MapperProxyFactory中,使用JDK的动态代理生成Mapper接口的代理代理类由动态处理器MapperProxy中调用MapperMethod中的方法处理执行SQL,最后,在MapperMethod中根据执行的方法返回值决定调用SqlSession中的对应方法执行SQL

动态SQL语句

Sql标签

       有如下标签:

if

表示判断是否需要添加某个条件,用于SQL语句的拼接

使用if标签的时候,需要使用“where 1=1”, 做sql语句的拼接。避免出现sql语法错误(因为缺少where关键字)

where

用于拼接select和delete语句

set

用于拼接update语句

trim

用于替代set和where标签,可以拼接select、delete、update语句

  • if标签
<select id="getEmps" parameterType="entity.Emp" resultType="entity.Emp">
    select * from emp where 1=1
    <if test="empName!=null">and empName=#{empName}</if>
    <if test="empAge!=0">and empAge > #{empAge}</if>
</select>
  • where标签
<select id="getEmpsByWhere" parameterType="entity.Emp" resultType="entity.Emp">
    select * from emp
    <!-- 如果if条件中,有为true的条件,那么会添加一个where关键字,同时会去掉where后面的第一个and关键字 -->
    <where>
        <if test="empName!=null">and empName=#{empName}</if>
        <if test="empAge!=0">and empAge > #{empAge}</if>
    </where>
</select>
  • set标签
<update id="updateEmpSet" parameterType="entity.Emp">
    update emp
    <!-- set标签 
        set中的if标签,条件为真的情况,就会拼在sql语句中, 将最后的“,”去掉。
        set中的if标签, 条件都为假的情况,就会出现sql语法错误。
    -->
    <set>
        <if test="empName!=null">empName=#{empName},</if>
        <if test="empAge!=0">empAge=#{empAge},</if>
        <if test="empJob!=null">empJob=#{empJob},</if>
        <if test="deptNo!=0">deptNo=#{deptNo}</if>
    </set>
    <where>
        <if test="empNo!=0">and empNo=#{empNo}</if>
    </where>
</update>
  • trim标签
<!-- trim的使用:替代set和where标签, 通过属性的设置,保证sql语句的语法正确 )
    prefix : 添加前缀 
    prefixOverrides: 删除前面的某个内容 
    suffix:  添加后缀 
    suffixOverrides: 删除后面的某个内容
-->
<!-- 替代where -->
<select id="getEmpsTrim" parameterType="entity.Emp" resultType="entity.Emp">
    select * from emp
    <trim prefix="where" prefixOverrides="and">
        <if test="empName!=null">and empName=#{empName}</if>
        <if test="empAge!=0">and empAge>#{empAge}</if>
        <if test="empJob!=null">and empJob like #{empJob}</if>
    </trim>
</select>
<!-- 替代set -->
<select id="updateEmpSet" parameterType="entity.Emp">
    update emp
    <trim prefix="set" suffixOverrides="," suffix=" where empNo=#{empNo}">
        <if test="empName!=null">empName=#{empName},</if>
        <if test="empAge!=0">empAge=#{empAge},</if>
        <if test="empJob!=null">empJob=#{empJob},</if>
        <if test="deptNo!=0">deptNo=#{deptNp}</if>
    </trim>
</select>

分页查询

    

select * from tableName limit begin, maxRow;
begin:查询数据的起点
maxRow:表示查询多少的数据(每页的数量)
分页:
每页显示的行数:maxRow
当前是第几页:page
计算出begin: begin
           (page-1)*maxRow
计算总页数:pages
          rows/maxRow + 1
计算总行数:rows
          select count(*) from tableName

导入分页查询插件jar包

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
    <version>5.1.10</version>
</dependency>

在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> 
     <!-- 分页插件的配置 -->
     <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor">
            <!-- 
              value:表示传入参数(page,rows)不合理时的处理方式
                为true时:若page表示的页面不存在时,如page<1,那么page设为1;如果page>最后一页,那么page设置为最后一页
                为false时:若page表示的页面不存在时,查询内容为空
            -->
            <property name="reasonable" value="true"></property>
        </plugin>
     </plugins>
    ....
	 
  </configuration>

使用相关类进行分页

public class TestStudent {
    @Test
    public void getStudents() throws IOException {
        SqlSession sqlSession = getSqlSession();
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
        //调用PageHelper的静态方法设置要分页的页码和每页显示的数量(需要先设置分页的参数,然后才能再查询数据库)
        PageHelper.startPage(5, 5);
        List<Student> students = studentMapper.getStudents();
        //PageInfo:存放分页相关数据,创建对象的时候,需要一个查询的结果List作为参数,
        //          需要设置泛型,泛型就是当前查询的实体类
        PageInfo<Student> pageInfo = new PageInfo<>(students);
        System.out.println("总记录数: " + pageInfo.getTotal());
        System.out.println("总页数: " + pageInfo.getPages());
        System.out.println("每页的数量: " + pageInfo.getPageSize());
        System.out.println("当前页: " + pageInfo.getPageNum());
        for (Student student : students) {
            System.out.println(student);
        }
    }
	
    public SqlSession getSqlSession() throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        return sessionFactory.openSession();
    }
}

使用MyBatis Generator插件

1.说明

      使用MyBatis Generator插件可以自动生成数据库对应的表的实体类,mapper映射器类和mapper.xml文件。

2.导入MyBatis Generator插件

      点击STS的Help选项,然后点击其中的Eclipse Marketplace。然后在搜索框里面搜索mybatis generator,然后点击下载安装MyBatis Generator插件。如下图所示:

3.使用

       在资源文件夹里面右键,点击new选择生成MyBatis Generator Configuration File。如下图所示:

      生成的文件如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" 
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
    <context id="context1">
        <jdbcConnection connectionURL="???" driverClass="???" password="???" userId="???" />
        <javaModelGenerator targetPackage="???" targetProject="???" />
        <sqlMapGenerator targetPackage="???" targetProject="???" />
        <javaClientGenerator targetPackage="???" targetProject="???" type="XMLMAPPER" />
        <table schema="???" tableName="???">
            <columnOverride column="???" property="???" />
        </table>
    </context>
</generatorConfiguration>

       然后根据所选的数据库表进行配置,配置好的如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" 
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
    <context id="context1">
        <!-- 数据库连接 -->
        <jdbcConnection connectionURL="jdbc:mysql://localhost:3306/crm?useUnicode=true&amp;
                                        characterEncoding=utf-8&amp;useSSL=false" 
    	            driverClass="com.mysql.jdbc.Driver" password="root" userId="root" />
        <!-- Java实体类所在包名称和项目名称 -->
        <javaModelGenerator targetPackage="com.luckylas.crm.entity" targetProject="crm/src/main/java" />
        <!-- mapper.xml所在的包(targetPackage)和所在的项目(targetProject) -->
        <sqlMapGenerator targetPackage="com.luckylas.crm.mapper.xml" targetProject="crm/src/main/java" />
        <!-- mapper所在的包(targetPackage)和所在的项目(targetProject) -->
        <javaClientGenerator targetPackage="com.luckylas.crm.mapper" 
                               targetProject="crm/src/main/java" type="XMLMAPPER" />
        <!-- tableName标签表示数据库中的表,可以有多个,
         schema:用于指定实体类的名字,不指定则默认是表名的首字母大写
        -->
        <table schema="User" tableName="user">
            <!-- columnOverride表示将数据库表中字段名,在实体类中取一个新的名字。如果不指定,则会默认值-->
            <!-- <columnOverride column="UId" property="u_id" /> -->
        </table>
    </context>
</generatorConfiguration>

一个简单的MyBatis实例

创建数据库实体类,和数据库字段一一对应

/**
 * 班级实体类
 * @author luckyliuqs
 */
public class TClass {
    private int cid;   //班级ID
    private String cname;  //班级名称
	
    public TClass() {}
	public TClass(int cid, String cname) {
        super();
        this.cid = cid;
        this.cname = cname;
    }
    public int getCid() { return cid;}
    public void setCid(int cid) {this.cid = cid;}
    public String getCname() {return cname;}
    public void setCname(String cname) {this.cname = cname;}
    @Override
    public String toString() {
        return "TClass [cid=" + cid + ", cname=" + cname + "]";
    }	
}

编写数据库接口Mapper类

public interface TClassMapper {
    public List<TClass> getAll();       //获取所有班级信息
    public int insert(TClass tClass);  //插入指定班级信息
    public void delete(int cid);        //删除指定班级信息
    public void update(TClass tClass);  //更新指定班级信息
}

编写接口类对应的Mapper文件

     如下所示:TClassMapper.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">
 <!-- namespace: 命名空间 (内容为接口Mapper类的全名),每一个Mapper.java会有一个对应的Mapper.xml件 -->
<mapper namespace="mapper.TClassMapper">
    <!-- id对应为接口Mapper类中的方法名 -->
    <!-- resultType表示返回结果的类型,这里写入TClass即可,如果返回结果是一个TClass则会返回这个TClass;
         如果返回的是多个TClass的集合,则会自动封装为List<TClass>返回 -->
    <select id="getAll" resultType="entity.TClass">
          select * from t_class;
    </select>
    
    <!-- #{s_name}, 这是从方法的参数对象中,取到参数对象中的属性名,得到其属性值 -->
    <insert id="insert" parameterType="tclassMap">
          insert into t_class (c_name) values (#{c_name});
    </insert>
    
    <delete id="delete">
          delete from t_class where c_id=#{c_id};
    </delete >
    
    <update id="update" parameterType="tclassMap">
          update t_class set c_name=#{cname} where c_id=#{c_id};
    </update >
</mapper>

编写JUnit测试类

/**
 * 测试类
 */
public class TestTClass {

    @Test
    public void test() {
        try {
            // mybatis的配置文件路径
            String resource = "mybatis-config.xml";
            // 获取到InputStream流,初始化MyBatis配置环境
            InputStream input = Resources.getResourceAsStream(resource);
            // 得到SqlSessionFactory
            SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(input);
            // 得到session,打开和数据库之间的会话
            SqlSession session = sessionFactory.openSession();
            // 得到接口
            TClassMapper clsMapper = session.getMapper(TClassMapper.class);
            //获取到所有班级信息
            List<TClass> list = clsMapper.getAll();
            for(TClass cl : list) {
                System.out.println(cl);
            }
            //插入指定班级信息
            TClass tClass = new TClass(0,"美工");
            clsMapper.insert(tClass);
            //删除指定班级信息
            clsMapper.delete(8);
            //更新指定班级信息
            clsMapper.update(tClass);
            //提交
            session.commit();
            session.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

          上述使用MyBatis流程如下:

1.获取MyBatis配置文件
2.获取配置文件的输入流InputStream
3.通过输出流构建工厂SqlSessionFactory
4.通过SqlSessionFactory的openSession()方法获得SqlSession对象
5.通过SqlSession获取到对应实体类的Mapper接口类实例
6.通过此接口类执行对应方法

MyBatis与Hibernate的区别

     两者都是持久层框架,区别如下:

Hibernate

是一个标准的ORM框架,比较重量级,学习成本高。

优点:高度封装,使用起来不用写SQL语句,开发周期短

缺点:SQL语句无法优化

应用场景:在于用量不大,并发量小的场景

MyBatis

不是一个ORM框架,只是对JDBC的轻量级封装。

优点:学习成本低,SQL语句可以优化,执行效率高,速度快

缺点:编码量大,开发周期长

应用场景:用户量大,高并发

参考:https://www.jianshu.com/p/24302ca0e099

发布了131 篇原创文章 · 获赞 39 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_35507234/article/details/100886161