01-MyBatis的基本使用

01、MyBatis的核心对象

Mapper(实际上是一个代理对象)是从SqlSession中获取的。它的作用是发送SQL来操作数据库的数据。它应该在一个SqlSession事务方法之内。

02、核心代码的简单调用

String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

SqlSession session = sqlSessionFactory.openSession();
try {
   Blog blog = (Blog) session.selectOne("com.mybatis.mapper.BlogMapper.selectBlogById", 1);
   System.out.println(blog);
} finally {
   session.close();
}

 

03、MyBatis核心配置

【1】、configuration

整个配置文件的根标签,对应的Configuration类,

【2】、properties

用来配置参数信息,比如最常见的数据库连接信息。在xml配置文件中用${}引用。

【3】、settings

setttings里面是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 resource="db.properties"></properties>
    <settings>
        <!-- 打印查询语句 -->
        <setting name="logImpl" value="STDOUT_LOGGING" />

        <!-- 控制全局缓存(二级缓存)-->
        <setting name="cacheEnabled" value="true"/>

        <!-- 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。默认 false  -->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!-- 当开启时,任何方法的调用都会加载该对象的所有属性。默认 false,可通过select标签的 fetchType来覆盖-->
        <setting name="aggressiveLazyLoading" value="false"/>
        <!--  Mybatis 创建具有延迟加载能力的对象所用到的代理工具,默认JAVASSIST -->
        <!--<setting name="proxyFactory" value="CGLIB" />-->
        <!-- STATEMENT级别的缓存,使一级缓存,只针对当前执行的这一statement有效 -->
        <!--
                <setting name="localCacheScope" value="STATEMENT"/>
        -->
        <setting name="localCacheScope" value="SESSION"/>
    </settings>

</configuration>

【4】、typeAliases

类型的别名。比如我们的参数类型和返回值类型都可能会用到我们的Bean,比如com.mybatis.domain.Blog都只要写blog就可以了。

【5】、typeHandlers【重点】

自定义Java类型和数据库的JDBC类型的相互转换规则。

说明:

1、类型处理器接口:TypeHandler

定义类型处理器的基本作用:从Java类型到JDBC类型和从JDBC类型到Java类型

2、类型引用:TypeReference

用于获取Java中的原生类型,即byte、short、int、long、float、double、boolean、char八大基本数据类型。为了持有这个具体的类型处理器所处理的Java类型的原生类型。

3、基础类型处理器:BaseTypeHandler

内部简单的实现了TypeHandler接口中定义的四个方法中实现了所有类型处理器公共部分

4、案例

public class MyTypeHandler extends BaseTypeHandler<String> {
    public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType)
            throws SQLException {
        // 设置 String 类型的参数的时候调用,Java类型到JDBC类型
        // 注意只有在字段上添加typeHandler属性才会生效
        // insertBlog name字段
        System.out.println("---------------setNonNullParameter1:"+parameter);
        ps.setString(i, parameter);
    }

    public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
        // 根据列名获取 String 类型的参数的时候调用,JDBC类型到java类型
        // 注意只有在字段上添加typeHandler属性才会生效
        System.out.println("---------------getNullableResult1:"+columnName);
        return rs.getString(columnName);
    }

    public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        // 根据下标获取 String 类型的参数的时候调用
        System.out.println("---------------getNullableResult2:"+columnIndex);
        return rs.getString(columnIndex);
    }

    public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        System.out.println("---------------getNullableResult3:");
        return cs.getString(columnIndex);
    }
}

 

【6】、plugins

插件。MyBatis预留了插件的接口,让MyBatis更容易扩展。

插件可以拦截这四个对象的这些方法,其中4个对象为MyBatis的四大对象。

Executor、ParameterHandler、ResultSetHandler、StatementHandler。

【7】、environments、environment

environments标签用来管理数据库的环境。

一个environment标签就是一个数据源,代表一个数据库。

如:

<environments default="development">
    <environment id="development">
        <transactionManager type="JDBC"/><!-- 单独使用时配置成MANAGED没有事务 -->
        <dataSource type="POOLED">
            <property name="driver" value="${jdbc.driver}"/>
            <property name="url" value="${jdbc.url}"/>
            <property name="username" value="${jdbc.username}"/>
            <property name="password" value="${jdbc.password}"/>
        </dataSource>
    </environment>
</environments>

【8】、transactionManager

配置事务

JDBC:使用Connection对象的commit()、rollback()、close()管理事务。

MANAGED:把事务交给容器来管理,比如JBOSS,Weblogic。

【9】、dataSource

数据源

【10】、mappers

映射器:Mapper.xml的路径。作用是让MyBatis在启动的时候去扫描这些映射器,创建映射关系。

总结:

Mybatis九大类全局配置节点按照如下顺序排序,位置不能颠倒。

properties=>settings=>typeAliases=>typeHandlers=>objectFactory=>plugins=>environment=>databaseIdProvider=>mappers

【11】、settings

设置MyBatis的一些最关键的配置

04、Mapper.xml映射配置文件【重点】

映射器里面最主要的是配置了SQL语句,也解决了我们的参数映射和结果集映射的问题。

8个标签

cache : 该命名空间的缓存配置

cache-ref : 引用其它命名空间的缓存配置。

resultMap – 描述如何从数据库结果集中加载对象,是最复杂也是最强大的元素。

<resultMap id="BaseResultMap" type="blog">
    <id column="bid" property="bid" jdbcType="INTEGER"/>
    <result column="name" property="name" jdbcType="VARCHAR"/>
    <result column="author_id" property="authorId" jdbcType="INTEGER"/>
</resultMap>

sql : 可被其它语句引用的可重用语句块。

<sql id="Base_Column_List">
    bid, name, author_id
</sql>

insert :映射插入语句

update : 映射更新语句

delete : 映射删除语句

select : 映射查询语句

 05、动态SQL

MyBaits的动态SQL基于OGNL表达。

【1】、if:需要判断的时候,条件写在test中

<select id="selectByExample" parameterType="com.BlogExample" resultMap="BaseResultMap">
    select
    *
    from blog
    <if test="_parameter != null">
        <include refid="Example_Where_Clause" />
    </if>
    <if test="orderByClause != null AND parameter != null">
        order by ${orderByClause}
    </if>
</select>

【2】、choose(when,otherwise):需要选择一个条件的时候

<select id="getEmpList_choose" resultMap="empResultMap" parameterType="com.Employee">
SELECT * FROMtbl_emp e
<where>
<choose>
    <when test="emp_id!=null">
        e.emp_id=#{emp_id,jdbcType=INTEGER}
    </when>
    <when test="emp_name!=null">
        AND e.emp_nameLIKE CONCAT(CONCAT('%',#{emp_name,jdbcType=VARCHAR}),'%')
    </when>
    <otherwise>
        
    </otherwise>
</choose>
</where>
</select>

【3】、trim(where,set):需要去掉where、and、逗号之类的符号的时候。

<update id="updateByPrimaryKeySelective" parameterType="com.Employee">
update tbl_emp
<set>
    <if test="empName!=null">
    emp_name=#{empName,jdbcType=VARCHAR},
    </if>
    <if test="dId!=null">
    d_id=#{dId,jdbcType=INTEGER},
    </if>
</set>
where emp_id=#{empId,jdbcType=INTEGER}
</update>

<insert id="insertSelective"  parameterType="com.Employee">
insert into tbl_emp
<trim prefix="(" suffix=")" suffixOverrides=",">
    <if test="empName!=null">
    emp_name,
    </if>
    <if test="dId!=null">
    d_id,
    </if>
</trim>
<trim prefix="values(" suffix=")" suffixOverrides=",">
    <if test="empName!=null">
    #{empName,jdbcType=VARCHAR},
    </if>
    <if test="dId!=null">
    #{dId,jdbcType=INTEGER},
    </if>
</trim>
</insert>

【4】、foreach:需要遍历集合的时候

<delete id="deleteByList"parameterType="java.util.List">
delete from tbl_emp where emp_idin
<foreach collection="list" item="item" open="(" separator="," close=")">
#{item.empId,jdbcType=VARCHAR}
</foreach>
</delete>

06、批量插入

MyBatis的动态标签的批量操作也是存在一定的缺点的,比如数据量特别大的时候,拼接出来的SQL语句过大。

MySQL的服务端对于接收的数据包有大小限制,max_allowed_packet默认是4M,需要修改默认配置才可以解决这个问题。

当然:在我们的全局配置文件中,可以配置默认的Executor的类型。其中有一种BatchExecutor。

<setting   name="defaultExecutorType"   value="BATCH"/>

也可以在创建会话的时候指定执行器类型:

SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH);

案例:

<insert id="batchInsert" parameterType="java.util.List" useGeneratedKeys="true">
insert into tbl_emp(emp_id,emp_name)
values         
<foreach collection="list" item="emps" index="index" separator=",">
(#{emps.empId},#{emps.empName})
</foreach>
</insert>

07、嵌套(关联)查询/N+1/延迟加载

【1】、resultType和resultMap的区别

resultMap功能更强大,可以通过设置typeHander来自定义实现功能。

【2】、一对一的关联查询有两种配置方式

1、嵌套结果

<!-- 根据文章查询作者,一对一查询的结果,嵌套查询 -->
<resultMap id="BlogWithAuthorResultMap" type="com.gupaoedu.domain.associate.BlogAndAuthor">
    <id column="bid" property="bid" jdbcType="INTEGER"/>
    <result column="name" property="name" jdbcType="VARCHAR"/>
    <!-- 联合查询,将author的属性映射到ResultMap -->
    <association property="author" javaType="com.gupaoedu.domain.Author">
        <id column="author_id" property="authorId"/>
        <result column="author_name" property="authorName"/>
    </association>
</resultMap>

2、嵌套查询

<!-- 另一种联合查询(一对一)的实现,但是这种方式有“N+1”的问题 -->
<resultMap id="BlogWithAuthorQueryMap" type="com.gupaoedu.domain.associate.BlogAndAuthor">
    <id column="bid" property="bid" jdbcType="INTEGER"/>
    <result column="name" property="name" jdbcType="VARCHAR"/>
    <association property="author" javaType="com.gupaoedu.domain.Author"
                 column="author_id" select="selectAuthor"/> <!-- selectAuthor 定义在下面-->
</resultMap>
<!-- 嵌套查询 -->
<select id="selectAuthor" parameterType="int" resultType="com.gupaoedu.domain.Author">
    select author_id authorId, author_name authorName
    from author where author_id = #{authorId}
</select>

08、翻页

PageHelper分页插件

原理拦截器,主要拦截Executor对象中的query(MappedStatement ms,Object o,RowBounds ob ResultHandler rh)这个方法。

09、mybatis-plus

参考:https://www.jianshu.com/p/ceb1df475021

10、PreparedStatement和statement的区别

.【1】、PreparedStatement是预编译的,对于批量处理可以大大提高效率. 也叫JDBC存储过程

【2】、使用 Statement 对象。在对数据库只执行一次性存取的时侯,用 Statement 对象进行处理。PreparedStatement 对象的开销比Statement大,对于一次性操作并不会带来额外的好处。

【3】、statement每次执行sql语句,相关数据库都要执行sql语句的编译,preparedstatement是预编译得,   preparedstatement支持批处理

©️2020 CSDN 皮肤主题: 成长之路 设计师:Amelia_0503 返回首页