Mybatis学习小结,超赞!!!

Mybatis学习小结

一.Mybatis前提知识

1.什么是Mybatis?

优秀的持久层开源框架

MyBatis 是一个半自动化的ORM框架 (Object Relationship Mapping) -->对象关系映射

2.什么是持久化层?

负责持久化过程的相对独立的逻辑层面

3.什么是持久化?

将内存中的对象存储在数据库中,或者存储在磁盘文件中、XML数据文件中

JDBC就是一种持久化机制。文件IO也是一种持久化机制

实现持久化过程大多通过关系数据库来完成

4.Mybatis有什么作用?

避免几乎所有的jdbc代码与和手动参数设置及获取结果集

使用简单的xml配置或注释来配置和映射原生信息,将java实体类(pojo对象)映射成数据库中的记录

5.使用Mybatis有什么好处?

与传统jdbc相比,可以减少很多的重复代码

使用mybatis不会对程序结构设计和数据库设计产生干扰,sql写在xml文件里(支持动态编写sql),便于统一管理和优化

解耦,将业务逻辑和数据访问分离,使系统设计更加清晰,更易于维护

二.简单实现Mybatis

1.搭实验工程与建库
2.导入依赖

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.2</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
</dependency>

3.写核心配置文件

在这里插入代码片<?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 resource="db.properties"/>
    
    <!--log4j日志-->
    <settings>
        <setting name="logImpl" value="LOG4J"/>
    </settings>
    
    <!--以小写字母作为别名-->
    <typeAliases>
        <package name="pojo"/>
    </typeAliases>

	<!--核心配置-->
    <!--环境配置,连接的数据库,这里使用的是MySQL-->
    <environments default="mysql">
        <environment id="mysql">
            <!--指定事务管理的类型,这里简单使用Java的JDBC的提交和回滚设置-->
            <transactionManager type="JDBC"></transactionManager>
            <!--dataSource 指连接源配置,POOLED是JDBC连接对象的数据源连接池的实现-->
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"></property>
                <property name="url" value="${url}"></property>
                <property name="username" value="${username}"></property>
                <property name="password" value="${password}"></property>
            </dataSource>
        </environment>
    </environments>
    
    <!--配置Mapper文件-->
    <!--<mappers>
        &lt;!&ndash;这是告诉Mybatis区哪找持久化类的映射文件,对于在src下的文件直接写文件名,
            如果在某包下,则要写明路径,如:com/mybatistest/config/User.xml&ndash;&gt;
        <mapper class="dao.UserMapper"/>
    </mappers>-->
    <mappers>
        <!--这是告诉Mybatis区哪找持久化类的映射文件,对于在src下的文件直接写文件名,
            如果在某包下,则要写明路径,如:com/mybatistest/config/User.xml-->
        <package name="dao"></package>
    </mappers>

</configuration>

4.mybatis工具类

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;
public class MybatisUtils {
    private static SqlSessionFactory sqlSessionFactory;
    static {
        try {
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //获取SqlSession连接
    public static SqlSession getSession(){
        return sqlSessionFactory.openSession();
    }
}

5.创建实体类

package pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
//@Alias()
@Data  //lombok注解
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private int id;
    private String name;
    private String pwd;
}

6.创建Mapper接口

import pojo.User;
import java.util.List;
public interface UserMapper {
    List<User> selectUser();
}

7.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">
        <mapper namespace="dao.UserMapper">
        <select id="selectUser" resultType="user">
          select * from user
        </select>
        </mapper>

8.测试

public class MyTest {
    @Test
    public void selectUser() {
        SqlSession session = MybatisUtils.getSession();
        //方法一:
        //List<User> users = session.selectList("dao.UserMapper.selectUser");
        //方法二:
        UserMapper mapper = session.getMapper(UserMapper.class);
        List<User> users = mapper.selectUser();
 
        for (User user: users){
            System.out.println(user);
        }
        session.close();
    }
}

9.可能出现的问题:Maven静态资源过滤问题,在pom文件中加入以下配置

<build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                    <include>**/*.yml</include>
                    <include>**/*.tld</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties</include>
                    <include>**/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>
</build>

有了MyBatis以后再也不用写原生的JDBC代码了,舒服!

三.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>

    <!--引入properties文件-->
    <properties resource="db.properties"/>
    <settings>
        <setting name="logImpl" value="LOG4J"/>
    </settings>
    
    <typeAliases>
        <package name="pojo"/>
    </typeAliases>

    <!--环境配置,连接的数据库,这里使用的是MySQL-->
    <environments default="mysql">
        <environment id="mysql">
            <!--指定事务管理的类型,这里简单使用Java的JDBC的提交和回滚设置-->
            <transactionManager type="JDBC"></transactionManager>
            <!--dataSource 指连接源配置,POOLED是JDBC连接对象的数据源连接池的实现-->
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"></property>
                <property name="url" value="${url}"></property>
                <property name="username" value="${username}"></property>
                <property name="password" value="${password}"></property>
            </dataSource>
        </environment>
    </environments>
    <!--<mappers>
        &lt;!&ndash;这是告诉Mybatis区哪找持久化类的映射文件,对于在src下的文件直接写文件名,
            如果在某包下,则要写明路径,如:com/mybatistest/config/User.xml&ndash;&gt;
        <mapper class="dao.UserMapper"/>
    </mappers>-->
    <mappers>
        <!--这是告诉Mybatis区哪找持久化类的映射文件,对于在src下的文件直接写文件名,
            如果在某包下,则要写明路径,如:com/mybatistest/config/User.xml-->
        <package name="dao"></package>
    </mappers>


</configuration>

1.environments元素:

  • dataSource:

unpooled(每次被请求时打开和关闭连接)
pooled(这种数据源的实现利用“池”的概念将 JDBC 连接对象组织起来)
jndi(这个数据源的实现是为了能在如 Spring 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI 上下文的引用)
数据源也有很多第三方的实现,比如dbcp,c3p0,druid等等

  • transactionManager

JDBC
MANAGER

2.mappers元素

映射器,定义映射SQL语句文件

3.typeAlias优化

指定一个包名,Mybatis会在包名下面搜索需要的JavaBean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名

Alias注解,设置别名

4.settings
Mybatis学习小结,超赞!!!

四.作用域和生命周期

Mybatis学习小结,超赞!!!

1.sqlSessionFactoryBuilder

sqlSessionFactoryBuilder用于创建sqlSessionFactory,成功后就失去作用,因此 SqlSessionFactoryBuilder 实例的最佳作用域是【方法作用域】(也就是局部方法变量)

2.sqlSessionFactory

SqlSessionFactory 可以被认为是一个数据库连接池,作用是创建sqlSession对象,一旦创建就要长期保存,直到不在使用mybatis;一般的应用中我们往往希望 SqlSessionFactory 作为一个单例,让它在应用中被共享。所以说 SqlSessionFactory 的最佳作用域是【应用作用域】

3.sqlSession

SqlSession 就相当于一个数据库连接(Connection 对象),你可以在一个事务里面执行多条 SQL,然后通过它的 commit、rollback 等方法,提交或者回滚事务。

所以它应该存活在一个业务请求中,处理完整个请求后,应该关闭这条连接,让它归还给 SqlSessionFactory,否则数据库资源就很快被耗费精光,系统就会瘫痪,所以用 try…catch…finally… 语句来保证其正确关闭;SqlSession 的最佳的作用域是【请求或方法作用域】

五.注解开发

@select
@update
@insert
@delete

Mybatis学习小结,超赞!!!

本质:jvm动态代理机制

六.执行流程

Mybatis学习小结,超赞!!!

七.动态SQL

官网描述:
MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其它类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句的痛苦。例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL 这一特性可以彻底摆脱这种痛苦。
虽然在以前使用动态 SQL 并非一件易事,但正是 MyBatis 提供了可以被用在任意 SQL 映射语句中的强大的动态 SQL 语言得以改进这种情形。
动态 SQL 元素和 JSTL 或基于类似 XML 的文本处理器相似。在 MyBatis 之前的版本中,有很多元素需要花时间了解。MyBatis 3 大大精简了元素种类,现在只需学习原来一半的元素便可。MyBatis 采用功能强大的基于 OGNL 的表达式来淘汰其它大部分元素。

-------------------------------
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
-------------------------------

1.if

<!--需求1:
根据作者名字和博客名字来查询博客!
如果作者名字为空,那么只根据博客名字查询,反之,则根据作者名来查询
select * from blog where title = #{title} and author = #{author}
-->
<select id="queryBlogIf" parameterType="map" resultType="blog">
    select * from blog where
    <if test="title != null">
        title = #{title}
    </if>
    <if test="author != null">
        and author = #{author}
    </if>
</select>

这样写我们可以看到,如果 author 等于 null,那么查询语句为 select * from user where title=#{title},但是如果title为空呢?那么查询语句为 select * from user where and author=#{author},这是错误的 SQL 语句,如何解决呢?请看下面的 where 语句!

2.where

<select id="queryBlogIf" parameterType="map" resultType="blog">
    select * from blog
    <where>
        <if test="title != null">
            title = #{title}
        </if>
        <if test="author != null">
            and author = #{author}
        </if>
    </where>
</select>

这个“where”标签会知道如果它包含的标签中有返回值的话,它就插入一个‘where’。此外,如果标签返回的内容是以AND 或OR 开头的,则它会剔除掉

3.Set

<!--注意set是用的逗号隔开-->
<update id="updateBlog" parameterType="map">
    update blog
      <set>
          <if test="title != null">
              title = #{title},
          </if>
          <if test="author != null">
              author = #{author}
          </if>
      </set>
    where id = #{id};
</update>

4.choose

有时候,我们不想用到所有的查询条件,只想选择其中的一个,查询条件有一个满足即可,使用 choose 标签可以解决此类问题,类似于 Java 的 switch 语句

<select id="queryBlogChoose" parameterType="map" resultType="blog">
    select * from blog
    <where>
        <choose>
            <when test="title != null">
                 title = #{title}
            </when>
            <when test="author != null">
                and author = #{author}
            </when>
            <otherwise>
                and views = #{views}
            </otherwise>
        </choose>
    </where>
</select>

5.sql片段

<sql id="if-title-author">
    <if test="title != null">
        title = #{title}
    </if>
    <if test="author != null">
        and author = #{author}
    </if>
</sql>
<select id="queryBlogIf" parameterType="map" resultType="blog">
    select * from blog
    <where>
        <!-- 引用 sql 片段,如果refid 指定的不在本文件中,那么需要在前面加上 namespace -->
        <include refid="if-title-author"></include>
        <!-- 在这里还可以引用其他的 sql 片段 -->
    </where>
</select>

注意:

①、最好基于 单表来定义 sql 片段,提高片段的可重用性

②、在 sql 片段中不要包括 where

6.Foreach

需求:我们需要查询 blog 表中 id 分别为1,2,3的博客信息

<select id="queryBlogForeach" parameterType="map" resultType="blog">
    select * from blog
    <where>
        <!--
        collection:指定输入对象中的集合属性
        item:每次遍历生成的对象
        open:开始遍历时的拼接字符串
        close:结束时拼接的字符串
        separator:遍历对象之间需要拼接的字符串
        select * from blog where 1=1 and (id=1 or id=2 or id=3)
      -->
        <foreach collection="ids"  item="id" open="and (" close=")" separator="or">
            id=#{id}
        </foreach>
    </where>
</select>

八.分页

一.limit分页
Mybatis学习小结,超赞!!!

二.RowBounds类分页

 @Test
    public void getUserByBounds() {
        RowBounds rowBounds = new RowBounds(1,2);
        List<User> userList = session.selectList("dao.UserMapper.selectUser",null,rowBounds);
    }

三.Mybatis的PageHelper插件

1.导入jar包
使用maven的直接添加依赖就好了,这次没有使用maven,导入以下两个jar包。
Mybatis学习小结,超赞!!!

2.配置分页插件
Mybatis学习小结,超赞!!!

3.PageHelper.startPage静态方法调用

PageHelper.startPage(request);
//紧跟着的第一个select方法会被分页
List<Country> list = countryMapper.selectIf(1);
//后面的不会被分页,除非再次调用PageHelper.startPage
List<Country> list2 = countryMapper.selectIf(null);

4.PageInfo用法

 PageHelper.startPage(pn, 5);
        //startPage后面紧跟查询就是一个分页查询。
        List<Employee> list = employeeService.selectByList();
        //使用PageInfo包装查询后的结果,只需要将PageInfo交给页面就行。
        //封装了详细的分页信息,包括我们查询出来的数据userList,传入连续显示的页数5。
        PageInfo<Employee> page = new PageInfo<Employee>(list, 5);

PageInfo.class是插件里的类,非常方便的调用,分页再次提高性能

    //当前页
    private int pageNum;
    //每页的数量
    private int pageSize;
    //当前页的数量
    private int size;
 
    //由于startRow和endRow不常用,这里说个具体的用法
    //可以在页面中"显示startRow到endRow 共size条数据"
 
    //当前页面第一个元素在数据库中的行号
    private int startRow;
    //当前页面最后一个元素在数据库中的行号
    private int endRow;
 
    //总记录数
    private long total;
    //总页数
    private int pages;
    //结果集
    private List<T> list;
 
    //前一页
    private int prePage;
    //下一页
    private int nextPage;
    //是否为第一页
    private boolean isFirstPage;
    //是否为最后一页
    private boolean isLastPage;
    //是否有前一页
    private boolean hasPreviousPage;
    //是否有下一页
    private boolean hasNextPage;
    //导航页码数
    private int navigatePages;
    //所有导航页号
    private int[] navigatepageNums;
    //导航条上的第一页
    private int navigateFirstPage;
    //导航条上的最后一页
    private int navigateLastPage;
 
    public PageInfo() {
        this.isFirstPage = false;
        this.isLastPage = false;
        this.hasPreviousPage = false;
        this.hasNextPage = false;
    }            

九.缓存

一、mybatis和同是持久层的hibernate一样,都存在着缓存机制,今天来说一下mybatis的缓存机制。
查询缓存来缓存数据,从而达到提高查询性能的要求,以提高我们项目的效率!!

二、mybatis的缓存机制有两级:

1.一级缓存:一级缓存mybatsi已近为我们自动开启,不用我们手动操作,而且我们是关闭不了的!!但是我们可以手动清除缓存。(SqlSession级别)

失效的情况:

1.查询条件不同
2.增删改操作
3.查询不同的Mapper.xml,不是同一个Sqlsession对象
4.手动清除缓存(clearCache)

2.二级缓存:二级缓存需要我们手动开启。(全局级别,基于namespace级别的缓存)

特点:
查出的数据都会被默认先放在一级缓存中
只有会话提交或者关闭以后,一级缓存中的数据才会转到二级缓存中
只要开启了二级缓存,我们在同一个Mapper中的查询,可以在二级缓存中拿到数据)

第一步在mybatis的全局配置文件中配置Setting属性,设置名为cacheEnabled的属性值为true即可

<settings>
		<!-- 
		开启二级缓存,这个全局的配置二级缓存
		默认是开启的,但是还是需要写上,防止版本的更新 
		-->
		<setting name="cacheEnabled" value="true"/>
</settings>	

第二步:在具体需要二级缓存的mapeer映射文件中开启二级缓存,值需要在相应的映射文件中添加一个cache标签即可

<!-- 开启二级缓存 -->
 	<cache></cache>	
上一篇:JDK 命令之 javadoc -- 生成API文档


下一篇:git删除中间的某些commit