MyBatis入门

MyBatis概述

MyBatis是一款优秀的持久层框架;MyBatis中文官网

持久层:可以立即保存在磁盘上,在这里可以理解成与数据库进行相关的操作(dao层就是数据持久层)。

MyBatis对JDBC功能进行轻量级的封装,避免了几乎所有的JDBC代码手动设置参数以及手动获取结果集的操作。
①提供了统一的数据库信息配置,统一放在一个xml文件中,读取就行;
②将sql语句提取到一个xml文件中,并提供了动态sql功能以及数据缓存;
③提供了结果自动映射封装,实现了ORM;

ORM: Object Relational Mapping 对象关系映射,将数据库中的记录与Java中对象进行关系映射。

④对JDBC原生接口进行封装,提供了一些mybatis自己的接口和类来实现。

MyBatis环境搭建

1.创建一个Maven项目;
可参考Maven搭建来完成。
2.导入MyBatis相关的依赖;
在pom.xml文件中导入mybatis,mysql依赖:

  <!--mysql-connector-java-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.16</version>
        </dependency>

  <!--mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.2</version>
        </dependency>

3.创建数据库表,创建对应的model类;
4.创建一个mybatis核心全局配置文件(可以配置数据库连接信息,配置sql映射文件,或者各种常用的设置);

<?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">
<!--mybatis核心配置文件-->
<configuration>

     <!--导入配置属性文件 该文件中存储连接数据库的信息  键值对-->
    <properties resource="文件名"></properties>

    <!--常用设置-->
    <settings>
        <!--启用日志功能,在运行时,可以将实际执行的sql细节打印到控制台-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
        <!--开启驼峰命名映射-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
       <!-- <setting name="autoMappingBehavior" value="FULL"/>-->
        <!--全局开启二级缓存-->
        <setting name="cacheEnabled" value="true"/>
    </settings>

    <!--配置类型简称-->
    <typeAliases>
        <package name="model类地址"/>
    </typeAliases>

    <!--配置连接数据库的信息-->
    <environments default="development">
        <environment id="development">
            <!--数据库事物管理配置-->
            <transactionManager type="JDBC"></transactionManager>
            <!--数据源配置  type="POOLED" 使用数据库连接池-->
            <dataSource type="POOLED">
                <property name="driver" value=" " />
                <property name="url" value=" "/>
                <property name="username" value=" " />
                <property name="password" value=" "/>
            </dataSource>
        </environment>
    </environments>

    <!--配置sql映射文件-->
    <mappers>
        <mapper resource="sql映射文件地址"></mapper>
    </mappers>

</configuration>

5.创建接口(用来定义进行一系列增删改查操作的方法)
6.创建sql映射文件;

<?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="接口地址">
      定义sql语句
</mapper>

7.测试
为方便测试,可以在pom.xml文件中配置单元测试插件。

<!--junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>provided</scope>
        </dependency>

配置完成后,创建一个测试方法,在方法最上面标志@Test,即可直接进行测试。

 @Test
    public void test() {
        //读取配置文件  mybatis-config.xml 全局核心配置文件名
        Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
        //创建 SqlSessionFactory
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
        //创建 SqlSession
        SqlSession sqlSession = sessionFactory.openSession();
        //获得接口代理对象
        sqlSession.getMapper(接口.class);
        //关闭sqlSession
        sqlSession.close();
    }

MyBatis使用接口介绍

1.SqlSessionFactory接口
使用SqlSessionFactory来创建SqlSession,一旦创建SqlSessionFactory就会在整个应用过程中始终存在。由于创建开销较大,所以没有理由去销毁在创建它,一个应用运行中也不建议多次创建。
2.SqlSession接口
SqlSession意味着创建与数据库连接会话,该接口中封装了对数据库操作的方法,与数据库完成会话后关闭,每与数据库交互一次,就需要创建一个SqlSession对象。
3.Mybatis-Dao层 Mapper 接口化开发
Mapper 接口开发方式只需要编写 Mapper接口,由 Mybatis框架创建接口的动态代理对象,使用sqlsession.getMapper(接口.class)获得代理对象。
Mapper接口开发需要遵循以下规范:
①Mapper.xml文件中的namespace与 mapper 接口的类路径相同;

<mapper namespace="mapper接口的类路径">

②Mapper接口方法名和 Mapper.xml 中定义的每个 statement 的 id 相同;

<select id="Mapper接口方法名" parameterType=" " resultMap=" ">

③Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql的parameterType的类型相同;
④Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同。

List<Student> findStudents(Student student);
<select id="findStudents" parameterType="Student" resultType="Student">

参数传递

1.当只有一个参数,且该参数类型为基本数据类型时,不需要做任何处理,mapper.xml中需要定义parameterType;

void method(int id);  //parameterType="int"

2.当只有一个参数,且该参数类型为引用类型时,需要使用@Param()进行绑定处理;

void method(@Param("column") String column);

3.当有两个或少量参数时,需要使用@Param()进行绑定处理;

void method(@Param("acc") String account, @Param("pwd") String password);

4.当参数数量较多时,可以将参数封装在对象中。

Admin method(Admin admin);

5.在传递参数时, #{}和${}两种方式对参数进行操作有何区别?

#{ }:占位符,是经过预编译的,编译好sql语句再取值,能够防止sql注入,更安全。

 <select id="login" resultType="Admin">
        select * from admin where account=#{acc} and password=#{pwd}
 </select>

${ }:拼接符,会传入参数字符串,将值拼接在sql中,取值以后再去编译sql语句,无法防止sql注入。
${ }主要用来动态的向sql中传入列名,比如排序 order by ${column}

 <select id="find"  resultType="Admin">
        select * from admin order by ${column}
 </select>

增删改查操作

1.新增操作

//接口中定义的方法,以新增管理员为例
void saveAdmin(Admin admin);

//Mapper.xml中定义的statement
//开启将生成的主键列,自动封装到对象中
//useGeneratedKeys="true" keyProperty="id"(对象中的id属性) keyColumn="id"(数据库中的id列)
<insert id="saveAdmin" parameterType="Admin" useGeneratedKeys="true" keyProperty="id" keyColumn="id">
      insert into admin(account,password)value (#{account},#{password})
</insert>

2.删除操作

//接口中定义的方法,以删除管理员为例
void deleteAdminById(int id);

//Mapper.xml中定义的statement
<delete id="deleteAdminById" parameterType="int">
      delete from admin where id=#{id}
</delete>

3.修改操作

//接口中定义的方法,以修改管理员为例
void updateAdmin(Admin admin);

//Mapper.xml中定义的statement
<update id="updateAdmin" parameterType="Admin">
     update admin set account=#{account},password=#{password} where id=#{id}
</update>

4.查询操作
(1).单表查询

//根据管理员id查询管理员信息
 Admin findAdminById(int id);
 
 //Mapper.xml中定义的statement
<select id="findAdminById" parameterType="int" resultType="Admin">
        select account,password from admin where id=#{id}
 </select>

(2).多表查询
以学生为例,根据学生id查询该学生的所有信息,包括宿舍信息,管理员信息;

Student findStudentById(int id);

方式一:关联查询

<!--resultMap标签可以自己自定义结果映射-->
    <resultMap id="studentMap" type="Student">
        <!--手动映射-->
        <id column="id" property="id"></id>
        <result column="num" property="num"></result>
        <result column="name" property="name"></result>
        <result column="gender" property="gender"></result>
        <result column="birthday" property="birthday"></result>
        <result column="oper_time" property="operTime"></result>

        <!--用来封装关联的对象信息 property="dorm" 就会创建一个关联的对象,将查询到的结果保存到对象中,再将该对象set到返回的结果Student中 -->
        <association property="dorm" javaType="Dorm">
            <result column="dormNum" property="num"></result>
        </association>
        <association property="admin" javaType="Admin">
            <result column="account" property="account"></result>
        </association>
    </resultMap>

<select id="findStudentById" parameterType="int" resultMap="studentMap">
            SELECT
              s.id,
              s.num,
              s.name,
              s.gender,
              s.birthday,
              s.oper_time,
              d.num dormNum,
              a.account
            FROM
              student s
              LEFT JOIN dorm d
                ON s.dormid = d.id
              LEFT JOIN admin a
                ON s.adminid = a.id
                where s.id=#{id}
    </select>

方式二:嵌套查询
若使用关联查询,sql语句过于繁琐,容易出错时,可以使用嵌套查询;嵌套查询会把sql分成多次查询,一步一步进行查询。

<!--可以先查询学生信息,再根据学生信息查询宿舍信息以及管理员信息-->
<resultMap id="studentMap1" type="Student">
        <!--手动映射-->
        <id column="id" property="id"></id>
        <result column="num" property="num"></result>
        <result column="name" property="name"></result>
        <result column="gender" property="gender"></result>
        <result column="birthday" property="birthday"></result>
        <result column="oper_time" property="operTime"></result>
        <association property="dorm" javaType="Dorm" column="dormid" select="findDormById"></association>
        <association property="admin" javaType="Admin" column="adminid" select="findAdminById"></association>
    </resultMap>
    
    <select id="findStudentById1" parameterType="int" resultMap="studentMap1">
          select id,num,name,gender,birthday,dormid,adminid,oper_time from student where id=#{id}
    </select>
    <select id="findDormById" resultType="Dorm">
        select num from dorm where id=#{dormid}
    </select>
    <select id="findAdminById" resultType="Admin">
        select account from admin where id=#{adminid}
    </select>

操作结果处理

1.简单类型输出映射
直接使用resultType:

<!--mybatis对java中常用的数据类型的全类名进行了简化-->
    <select id="adminCount" resultType="int">
       select count(*) from admin
    </select>

2.对象映射
若返回的数据为一个对象时,mybatis会自己创建给定类的对象,并将查询到的结果自动封装到该对象中,进行返回。但自动封装是有条件的:
①开启了全局的自动结果映射 默认情况是单张表开启的;

<setting name="autoMappingBehavior" value="FULL"/>

②数据库列名与属性名字相同 不相同无法映射 可以定义别名使其相同;
③开启驼峰命名自动映射,由于数据库命名规则与Java不同,java中使用标准驼峰命名,数据库中使用下划线连接命名(admin_gender与adminGender可自动映射);

<setting name="mapUnderscoreToCamelCase" value="true"/>

3.特殊结果处理定义resultMap

 //根据id查询宿舍信息(该宿舍中的入住学生信息)
    Dorm findDormById(int id);

关联查询结果映射:

<!--结果映射-->
<resultMap id="dormMap" type="Dorm">
        <!--手动映射  column为数据库中的列名,property为Java类中的属性名
          id 标签映射主键,result标签映射非主键-->
        <id column="id" property="id"></id>
        <result column="num" property="num"></result>
        <!--映射的属性为一个对象-->
        <!--用来封装关联的对象信息 property="dorm" 就会创建一个关联的对象,将查询到的结果保存到对象中,再将该对象set到返回的结果Student中 -->
        <association property="admin" javaType="Admin">
            <result column="account" property="account"></result>
        </association>
        <!--映射的属性为一个集合-->
        <collection property="students" javaType="list" ofType="Student">
            <result column="snum" property="num"></result>
            <result column="name" property="name"></result>
        </collection>
  </resultMap>

   <!--resultMap 引用了 dormMap-->
    <select id="findDormById" parameterType="int" resultMap="dormMap">
        SELECT
              d.id,
              d.num,
              s.num snum,
              s.name,
              a.account
            FROM
              dorm d
              LEFT JOIN admin a
                ON d.adminid = a.id
              LEFT JOIN student s
                ON d.id = s.dormid
            WHERE d.id = #{id}
    </select>

嵌套查询结果映射:

<resultMap id="dormMap1" type="Dorm">
        <id column="id" property="id"></id>
        <result column="num" property="num"></result>
        <!--select属性指定关联查询对象的Statement ID-->
        <!--column属性将查询到的值传入select指定的Statement中-->
        <association property="admin" javaType="Admin" column="adminid" select="findAdmin"></association>
        <collection property="students" javaType="list" ofType="Student" column="id" select="findStudents"></collection>
    </resultMap>

    <select id="findDormById1" parameterType="int" resultMap="dormMap1">
         select id,num,adminid from dorm where id=#{id}
    </select>
    <select id="findAdmin" resultType="Admin">
         select account from admin where id=#{adminid}
    </select>
    <select id="findStudents" resultType="Student">
         select num,name from student where dormid=#{id}
    </select>

注解方式

常用注解标签:(简单操作可使用注解标签)
@Insert : 插入 sql , 和 xml insert sql 语法完全一样
@Select :查询 sql, 和 xml select sql 语法完全一样
@Update :更新 sql, 和 xml update sql 语法完全一样
@Delete : 删除 sql, 和 xml delete sql 语法完全一样
@Param : 入参
@Results : 设置结果集合
@Result : 结果
使用时,将sql语句写到注解标签中即可:

 @Select("select account,password from admin where id=#{id}")
    Admin findAdminById(int id);

动态SQL

在JDBC或者其他类似的框架中,需要根据不同的条件对sql语句进行拼接,根据sql语句的格式在拼接时需要注意是否添加了必要的空格,是否删掉了最后一个列名的逗号等等,这很令人痛苦,而动态sql解决了该问题。

动态SQL:一般是根据用户输入或者外部条件动态组合sql语句块,MyBatis可以在xml映射文件中,以标签的方式,完成逻辑判断和动态拼接sql的功能。

①where + if 标签

<!--
  where标签,当where标签内的if有成立的,就会动态的添加where关键字,如果where后面有and,or这种关键字会被动态删除
  if 标签,test="条件"-->
<select id="findStudents1" parameterType="Student" resultType="Student">
        select * from student
         <where>
             <if test="num!=null">
                 and num=#{num}
             </if>
             <if test="name!=null">
                 and name=#{name}
             </if>
             <if test="gender!=null">
                 and gender=#{gender}
             </if>
         </where>
</select>

②trim标签

<!--trim 标签  prefix="where"可以自定义指定关联字  prefixOverrides="and|or" 覆盖掉指定的开头的关键字-->
 <select id="findStudents1" parameterType="Student" resultType="Student">
        select * from student
        <trim prefix="where" prefixOverrides="and|or">
            <if test="num!=null">
                and num=#{num}
            </if>
            <if test="name!=null">
                and name=#{name}
            </if>
            <if test="gender!=null">
                and gender=#{gender}
            </if>
        </trim>
 </select>

③choose,when,otherwise标签

<!--只选择一个  如同Java中的if   else if  else -->
<select id="findStudents1" parameterType="Student" resultType="Student">
        select * from student
          <choose>
                <when test="num!=null">
                    num=#{num}
                </when>
                <when test="name!=null">
                  and name=#{name}
                </when>
                <otherwise>
                    gender=#{gender}
                </otherwise>
          </choose>
 </select>

④set标签

<!-- set关键字 可以动态的添加set关键字,可以去除最后的逗号也可以使用trim prefix="set" suffixOverrides=","-->
<update id="updateStudent" parameterType="Student">
        update student
        <set>
            <if test="num!=null">
                num=#{num},
            </if>
            <if test="name!=null">
                name=#{name},
            </if>
            <if test="gender!=null">
                gender=#{gender}
            </if>
        </set>
        where id=#{id}
</update>

⑤foreach标签

 <!--foreach 标签 可以遍历集合数组  collection="list" collection="array"-->
    <delete id="deleteStudents" parameterType="list">
        delete from student where id in
        <foreach collection="list" item="id" open="(" separator="," close=")">
            #{id}
        </foreach>
    </delete>

特殊符号处理

在 mybatis中的 xml 文件中,存在一些特殊的符号,比如:<、>、"、&、<>等,正常书写mybatis会报错,需要对这些符号进行转义。具体转义如下所示:
在这里插入图片描述
除了可以使用上述转义字符外,还可以使用<![CDATA[ ]]>来包裹特殊字符。

<![CDATA[ ]]>是 XML 语法。在 CDATA 内部的所有内容都会被解析器忽略。但是有个问题那就是但是有个问题那就是 等这些标签都不会被解析,所以我们只把有特殊字符的语句放在 <![CDATA[ ]]>尽量缩小<![CDATA[ ]]>的范围。

缓存机制

缓存:将一些数据临时存储,为了更快的获取到数据。

mybatis为减轻数据库压力,提高数据库性能,提供了两种缓存机制:
1.一级缓存
SqlSession级别的缓存,缓存的数据只在SqlSession内有效。
mybatis默认开启了一级缓存,是在同一个SqlSession中如果有两次相同的查询,只发送一次sql。mybatis将查询到的数据默认会缓存到SqlSession中。
由于以及缓存是默认开启的,无法关闭,但可以手动清空缓存:

方式一:sqlSession.clearCache(); 清除一级缓存中的数据
方式二:sqlSession.close();
方式三:中间执行了新增,修改,删除等操作会清空缓存(防止脏读);

一级缓存声明周期:
生:创建sqlSession ,可以通过以上三种方式手动销毁。
2.二级缓存
SqlSessionFactory级别的缓存,只有一个,sqlSession1查询到的数据保存在sqlSessionFactory中,即使sqlSession1销毁,sqlSession2也可以拿到该数据。
开启二级缓存:
①全局核心配置文件设置开启

<!--全局开启二级缓存-->
<setting name="cacheEnabled" value="true"/>

②model类实现序列化接口

public class 类名 implements Serializable {
......
}

③配置映射文件(更加细致的配置二级缓存)

<!--在Mapper.xml中更加细致的配置二级缓存
eviction="FIFO"  先进先出:按对象进入缓存的顺序来移除它们
size="512"  最多可以存储结果对象或列表的 512 个引用
readOnly="true"  返回的对象被认为是只读的
flushInterval="60000"  每隔 60 秒刷新
-->
    <cache eviction="FIFO" size="512" readOnly="true" flushInterval="60000"/>
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值