MyBatis技术总结

MyBatis技术总结

分类:JavaEE框架技术原创文章
作者:汪萍萍

  • 什么是MyBatis?

    MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。

  • MyBatis中的主要组成部分

    SqlSessionFactoryBuilder( 工厂构造器 ,使用了建造者模式) :根据配置文件来生成SqlSessionFactory。这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。 因此SqlSessionFactoryBuilder 实例的最佳作用域是方法作用域(也就是局部方法变量)。 你可以重用 SqlSessionFactoryBuilder 来创建多个 SqlSessionFactory 实例,但最好还是不要一直保留着它,以保证所有的 XML 解析资源可以被释放给更重要的事情。

    SqlSessionFactory(SqlSession工厂,使用到了工厂模式):创建SqlSession。

    SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。 使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建 SqlSessionFactory 被视为一种代码“坏习惯”。因此 SqlSessionFactory 的最佳作用域是应用作用域。 有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。

    SqlSession(会话):执行SQL并返回结果。每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。 绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。 也绝不能将 SqlSession 实例的引用放在任何类型的托管作用域中,比如 Servlet 框架中的 HttpSession。 如果你现在正在使用一种 Web 框架,考虑将 SqlSession 放在一个和 HTTP 请求相似的作用域中。 换句话说,每次收到 HTTP 请求,就可以打开一个 SqlSession,返回一个响应后,就关闭它。 这个关闭操作很重要,为了确保每次都能执行关闭操作,你应该把这个关闭操作放到 finally 块中。 下面的示例就是一个确保SqlSession 关闭的标准模式:MyBatis主要由Resources、SqlSessionFactoryBuilder。。。。。组成。
    SQL Mapper:由一个Java接口和XML文件(或注解)构成。接口负责定义数据访问接口,XML文件(或注解)负责定义SQL和映射规则

    Sql Mapper:由Java接口和xml文件构成,Mapper代表一个请求中的业务处理,一旦完成了相关的业务就该废弃它。随着SqlSession的归还,它的数据库连接资源也会消失,所以他的生命周期应该小于等于SqlSession的生命周期

    • SqlSessionFactory创建代码实例
//1.读取配置文件
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
            
//2.创建SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
  • SqlSession创建代码实例
//3.创建SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
System.out.println("SqlSession接口的实现类对象:" + sqlSession);
  • MyBatis 配置
  • 加载外部配置文件
<!-- 加载外部的properties文件 -->
    <properties resource="jdbc.properties"/>
    
  • 设置(settings)
    主要作用:MyBatis框架运行规则配置
    设置(settings)代码示例
<settings>
        <!-- 开启日志 -->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>

typeAliases为实体类设置别名

<typeAliases>
<!-- 为类名取别名(实体类) -->
<!-- <typeAlias type="com.apesource.entity.Employee" alias="Employee"/> -->

        <!-- 设置实体类包,为该package中的每个实体类自动设置别名 -->
        <package name="com.apesource.entity"/>
    </typeAliases>
  • 环境配置(environments)

    主要作用:完成Mybatis中的多环境配置
    环境配置(environments)代码示例:

<!-- 环境  default默认环境 -->
  <environments default="development">
  
  <!-- id 开发环境(开发) -->
    <environment id="development">
    
    <!-- 事务管理  "JDBC" -->
      <transactionManager type="JDBC"/>
 
 <!-- 数据源 (使用数据连接池 )-->
      <!-- type设置为pooled,启动数据库连接池-->
      <dataSource type="POOLED">
      
      <!-- 数据库连接参数 -->
        <property name="driver" value="${driver_class}"/>
        
        <!-- 连接字符串 -->
        <property name="url" value="${jdbc_url}"/>
       
        <property name="username" value="${db_username}"/>
       
        <property name="password" value="${db_password}"/>
      </dataSource>
    </environment>
  </environments>
  • 映射器(mappers)

    主要作用:指定映射文件路径
    映射器(mappers)代码实例

    <!--映射器列表-->
    <mappers>
     <!--SQL映射文件-->
          <mapper resource="com/apesoure/mapper/EmployeeMapper.xml"/> 
      </mappers>
    
  • MyBatis XML映射器

    1:常用节点作用总结

  • select:映射SQL查询语句select
  • update:映射SQL修改语句update
  • delete:映射SQL删除语句delete
  • insert:映射SQL增加语句insert
    2:常用属性作用总结
  • id属性:为当前映射的SQL语句进行命名,id应该与xxxMapper接口下的方法名一致
  • reultType属性:设置查询结果使用的类型名称
  • parameterType属性:设置执行操作时使用的参数类型
  • useGeneratedKeys属性:设置为true表示开启逐渐回填
  • keyProperty属性:设置用于保存主键值的属性名称
    3:常见SQL映射实例
    示例1:添加数据
<insert id="insertAnswerRecord" parameterType="AnswerRecord"
        useGeneratedKeys="true" keyProperty="recordId">
        insert into
        answer_record(respondent,question,right_answer,submit_answer,submit_datetime)
        values(#{respondent},#{question},#{rightAnswer},#{submitAnswer},now())
    </insert>

mappper接口定义方法

int insertAnswerRecord(AnswerRecord answerRecord);

示例2:批量增加:

<!-- foreach:用于动态SQL中的循环遍历,collection指定遍历的集合类型,item为每次循环遍历的元素命名 -->
    <insert id="insertAnswerRecordBatch" 
            parameterType="list"
            useGeneratedKeys="true" keyProperty="recordId">
        INSERT INTO answer_record(respondent,question,right_answer,submit_answer,submit_datetime)
        VALUES
        <foreach collection="list" item="record" separator=",">
            (
                #{record.respondent},
                #{record.question},
                #{record.rightAnswer},
                #{record.submitAnswer},
                now()
            )
        </foreach>
    </insert>

接口方法定义:
int insertAnswerRecordBatch(List<AnswerRecord> answerRecordList);
示例3:普通删除

<delete id="deleteAnswerRecord">
        delete from answer_record
        where record_id = #{id}
    </delete>

接口中方法定义

int deleteAnswerRecord(@Param("id")int recordId);

示例4:批量删除

<delete id="deleteAnswerRecordBatch"
            parameterType="list">
        DELETE FROM answer_record
        WHERE record_id IN
        <foreach collection="list" item="rid" separator="," open="(" close=")">
            #{rid}
        </foreach>
    </delete>

接口中方法定义

int deleteAnswerRecordBatch(List<Integer> recordIdList);

示例5:动态修改

<!-- set节点用于动态处理update语句中的set -->
    <!-- if节点用于条件判断 -->
<update id="updateAnswerRecord" parameterType="AnswerRecord">
        update answer_record
        <set>
            <if test="respondent!=null">respondent = #{respondent},</if>
            <if test="question!=null">question = #{question},</if>
            <if test="rightAnswer!=null">right_answer = #{rightAnswer},</if>
            <if test="submitAnswer!=null">submit_answer = #{submitAnswer},</if>
            submit_datetime = now()
        </set>
        where record_id = #{recordId}
    </update>

接口中方法定义

int updateAnswerRecord(AnswerRecord answerRecord);

示例6:动态查询

<!-- where节点:处理where子句和条件之间的关系 -->
<select id="listAnswerRecordByCondition"
        resultType="AnswerRecord" 
        parameterType="AnswerRecord">

        SELECT record_id AS recordId,
        respondent,
        question,
        right_answer AS rightAnswer,
        submit_answer AS submitAnswer,
        submit_datetime AS submitDatetime
        FROM answer_record
<!--where会自动匹配条件中的and条件-->
<!--conact用来拼接字符串-->
        <where>
            <if test="respondent != null">
                AND respondent = #{respondent}
            </if>

            <if test="question != null">
                AND question LIKE concat('%',#{question},'%')
            </if>

            <if test="rightAnswer != null">
                AND right_answer = #{rightAnswer}
            </if>

            <if test="submitAnswer != null">
                AND submit_answer = #{submitAnswer}
            </if>
        </where>
    </select>

接口中定义方法

List<AnswerRecord> listAnswerRecordByCondition(AnswerRecord condition);

示例7:查询结果封装为Map

<select id="countAnswerRecordDataByRespondent"
            resultType="map">
        SELECT count(record_id) as total,
             (SELECT count(record_id) FROM answer_record WHERE respondent = #{name} AND right_answer = submit_answer ) as right_count,
             (SELECT count(record_id) FROM answer_record WHERE respondent = #{name} AND right_answer != submit_answer ) as fail_count
        FROM answer_record
        WHERE respondent = #{name}
        
    </select>

接口中定义方法

Map<String,Integer> countAnswerRecordDataByRespondent(@Param("name") String respondent);
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容