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与Hibernate的区别

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

Hibernate

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

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

缺点:SQL语句无法优化

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

MyBatis

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

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

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

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

 

一个简单的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.通过此接口类执行对应方法

 

 

 

 

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

 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luckyliuqs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值