mybatis框架

目录

框架

java后端框架

mybatis

背景

介绍

mybatis搭建

搭建补充

1.在idea中安装mybatisX插件

2.数据库连接池

3.单元测试

4.#{}与${}的区别

参数传递

1.单个参数传递

2.多个参数传递

2.1 使用@Param("account")来绑定

2.2 使用对象来传递

数据库事务

增删改查

1.增

2.删

3.改

关联查询

方式1:多表查询

方式2:嵌套查询

关联的结果中包含集合

动态SQL

if标签

where标签

trim标签

choose、when、otherwise标签

foreach标签

特殊符号处理

1.使用转义字符 

2. 使用  标签

缓存

mybatis  一级缓存

一级缓存生命周期

mybatis 二级缓存

配置二级缓存配置

第一步:启用二级缓存

第二步:对象序列化

第三步:配置映射文件


框架

对技术的封装,将基础的技术进行封装,让程序员可以快速的使用,提高开发效率

java后端框架

mybatis

    对jdbc进行封装

spring

    对整个java后端构架进行管理的

springweb

    对web层(servlet)继续封装

springboot

    对spring框架的搭建进行封装

mybatis

背景

原来是apache下面的一个开源项目,名为ibatis,2010年开发团队转移到谷歌旗下,改名为mybatis

Mybatis 中文官网
        mybatis – MyBatis 3 | 简介

介绍

        mybatis是一款优秀的持久层(数据持久层)框架(数据持久层----dao层 也称为 数据访问层)

        mybatis是对jdbc进行的封装,避免了jdbc中手动设置参数,手动映射结果的操作

        mybatis将jdbc中的接口进行封装,提供了他自己的类和接口实现

        mybatis可以使用xml配置和注解的方式,将数组库中记录自动映射到java对象中

        是一直ORM实现(对象关系映射) 可以自动将数据映射到对象中的这种框架,也称为orm框架

        mybatis还提供了 动态sql 和 数据缓存

mybatis搭建

      1.创建一个maven项目

      2.导入mybatis依赖的jar包

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

      3.在src.main.resources下创建一个全局的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>
<!-- 上面都是固定内容,下面才开始改变 -->

    <!--mybatis核心全局配置文件-->
    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
        <!--java中使用标准驼峰命名,数据库中使用下划线连接命名,可以开启全局设置实现自动转换-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
    
    <!--为类配置别名-->
    <typeAliases>
        <package name="com.ffyc.mybatispro.model"/>
    </typeAliases>
    
    <!--配置数据库链接相关信息-->
    <environments default="development">
        <environment id="development">

            <transactionManager type="JDBC"/>
            <!-- type="POOLED"  使用数据库连接池功能,默认创建了10个链接对象,减少频繁创建销毁链接对象 -->
            <dataSource type="POOLED">
                <!--数据库连接配置-->
                <property name="driver" value="com.mysql.cj.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/ssmdb?serverTimezone=Asia/Shanghai" />
                <property name="username" value="数据库的账号" />
                <property name="password" value="数据库的密码"/>
            </dataSource>
        </environment>

    </environments>

    <!--注册映射文件-->
    <mappers>
        <mapper resource="mappers/AdminMapper.xml"></mapper>
    </mappers>
</configuration>

​

      4.创建数据库,创建表,准备数据

      5.创建一个访问接口,定义方法

​​package com.ffyc.mybatispro.dao;

public interface AdminDao {
    Admin findAdminById(int id);
}

      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">
<!--
    sql映射文件: 主要写sql实现
-->
<mapper namespace="com.ffyc.mybatispro.dao.AdminDao">
    <!--id:方法名   ,parameterType:参数类型      ,resultType:返回值类型 -->
    <select id="findAdminById" parameterType="int" resultType="Admin">
        select * from admin where id = #{id}
    </select>
</mapper>

    7.测试mybatis

        //1.mybatis读取文件
        Reader reader = Resources.getResourceAsReader("mybatis.xml");

        //2创建SqlSessionFactory,  负责创建SqlSession对象(连接数据库的会话对象,类似Connection)
        //   SqlSessionFactory对象也只需要创建一个,创建后不需要销毁
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);

        //3.创建SqlSession 对象
        SqlSession sqlSession = sqlSessionFactory.openSession();

        //4.创建接口的代理对象
        AdminDao adminDao = sqlSession.getMapper(AdminDao.class);

        //5.调用
        Admin admin = adminDao.findAdminById(1);
        //让代理对象帮我们调用映射文件中与此接口中相同名称的方法

        System.out.println(admin);

        //6.关闭会话对象
        sqlSession.close();

搭建补充

1.在idea中安装mybatisX插件

打开Settings找到下图的内容

进入插件市场,搜索mybatisX并下载

2.数据库连接池

        链接数据库时,每次访问数据库时创建一个Connection,用完关闭

        但当访问量大了后,每次都要创建新的连接对象,用完关闭,比较耗时

使用数据库连接池,在(集合)中事先创建一些连接对象,

用户访问时,直接从池中获取一个链接对象,

用完不销毁,还回到池中,这样减少频繁创建连接对象

3.单元测试

程序员使用的测试方式,以方法为单位测试 使用junit组件实现单元测试

导入junit依赖的jar包

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

使用方法,在方法名前加上@Test

    @Test
    public void insert(){
        System.out.println("新增");
    }
4.#{}与${}的区别

#{}是占位符,是采用预编译方式向sql中传值,可以防止sql注入,如果我们往sql中传值,使用#{}

${}是将内容直接拼接到sql语句中,一般不用于向sql中传值,一般用于向sql动态传递列名

1.底层实现不同:

#{}采用预编译方式,可以防止sql注入,更加安全

${}采用字符串拼接,直接将值拼接到sql中

使用场景不同

#{}一般用于向sql中的列传值

${}一般用于向sql动态传递列名

例如 排序时 order by 后面的列名是可以改变的 例如 select 后面的列名也可以自由选择

参数传递

1.单个参数传递

如上述步骤中所示

2.多个参数传递
2.1 使用@Param("account")来绑定
Admin login1(@Param("acc") String account, @Param("pwd") String password);

在映射文件中

<select id="login1"  resultType="Admin">
    select * from admin where account = #{acc} and password = #{pwd}
</select>
2.2 使用对象来传递
Admin login(Admin admin);

映射文件中,传递的参数不需要使用对象名.属性名来表示,在{}中写属性名即可

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

数据库事务

是数据库的一种管理的机制,是对一次连接数据库过程的管理

能保证一次操作中执行的多条sql,要么都成功执行,要么都不执行

增删改查

增加,修改,删除完毕后,都需要手动提交事务

原因:提交数据库事务,当我们的程序代码执行没有任何问题时,才会向数据库发送提交事务操纵,数据库真正执行sql,出现异常则不提交事务

有时一次操作需要向数据库发送多条sql,数据库需要程序最终执行没有问题,向数据库提交事务后,才在数据库中执行sql,确保一次操作中的多条sql,要么都成功,要么都不成功

例如:转账时,我们需要将A账号的存款减去(sql1),再将B账户的存款增加(sql2),但在两个sql中间仍存在一些代码逻辑,这些代码也可能出现异常,若出现异常,我们不能将sql1执行,而sql2不执行,因此使用了事务,当出现异常时,代码中断,无法提交事务,也就不会改变数据库的数据,只有提交了事务,数据库才会真正执行这一次操作中的多条sql

1.增

保存数据后,需要立刻拿到这条数据在数据库的主键

void inserAdmin(Admin admin);

映射文件中,新增数据时需要返回新增数据的主键,因此需要在insert标签中添加下面的属性

useGeneratedKeys="true"  返回自增主键

keyProperty="id"  定义接收的属性   property(类中的属性)

keyColumn="id"  定义主键列    column(数据库中的列)

<insert id="inserAdmin" parameterType="Admin" useGeneratedKeys="true" keyProperty="id" keyColumn="id">
    insert into admin(account,password,gender) values(#{account},#{password},#{gender})
</insert>

调用时,需要获取新增数据的主键,并提交数据库事务

    @Test
    public void insert(){
        System.out.println("新增");
        Admin admin = new Admin();
        admin.setAccount("aaa");
        admin.setPassword("123");
        admin.setGender("男");
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        AdminDao adminDao = sqlSession.getMapper(AdminDao.class);
        adminDao.inserAdmin(admin);//保存数据后,拿到这条数据在数据库的主键
        System.out.println(admin.getId());

        sqlSession.commit();//提交数据库事务
        sqlSession.close();
    }
2.删
void deleteAdmin(int id);

映射文件中

<delete id="deleteAdmin">
    delete from admin where id = #{id}
</delete>
3.改
void updateAdmin(Admin admin);

映射文件中

<update id="updateAdmin" parameterType="Admin">
    update admin set account=#{account},password=#{password} where id=#{id}
</update>

关联查询

使用resultMap标签

方式1:多表查询
    <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>
        <!--映射关联数据 专业名称 首先会创建一个Major对象,然后将专业名称封装到Major对象中,最后将Major对象封装到Student对象中-->
        <association property="major" javaType="Major" >
            <result column="mname" property="name"></result>
        </association>
    </resultMap>


    <select id="findStudentById" resultMap="studentMap" >
        select
            s.id,
            s.num,
            s.name,
            s.gender,
            m.name mname
        from student s inner join major m on s.majorid=m.id
        where s.id=#{id};
    </select>
方式2:嵌套查询

先查询主表(学生表),再查询专业表

    <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>
        <!--与方法1不同之处-->
        <association property="major" javaType="Major" select="findMajorById" column="majorid">
        </association>
    </resultMap>
    <select id="findStudentById1" resultMap="studentMap1" >
        select id,num,name,gender,majorid
        from student
        where id=#{id};
    </select>
    <!--嵌套查询学生关联的专业-->
    <select id="findMajorById" resultType="Major">
        select name from major where id = #{majorid}
    </select>
关联的结果中包含集合

例如:查询专业时,将查询的多个学生封装到一个集合中,但这种方法在分页时会出现问题

<resultMap id="majorMap" type="Major">
    <id column="id" property="id"></id>
    <result column="name" property="name"></result>
    <!--将查询关联到的多条结果封装到集合中-->
    <collection property="students" javaType="List" ofType="Student">
        <result column="num" property="num"></result>
        <result column="sname" property="name"></result>
    </collection>
</resultMap>
<select id="findMajor" resultMap="majorMap">
    select
        m.id,
        m.name,
        s.num,
        s.name sname
    from major m left join student s on s.majorid=m.id
</select>

解决方法:分成两次查询

<resultMap id="majorMap1" type="Major">
    <id column="id" property="id"></id>
    <result column="name" property="name"></result>
    <!--将查询关联到的多条结果封装到集合中-->
    <collection property="students" javaType="List" ofType="student" select="findStudents" column="id"></collection>
</resultMap>
<select id="findMajor1" resultMap="majorMap1">
    select id,name from major
</select>
<select id="findStudents" resultType="student">
    select num,name from student where majorid=#{id}
</select>

动态SQL

在sql中添加逻辑判断

if标签

标签if中含有test属性,如果test属性的条件成立,就执行if的标签体,反之则不执行

where标签

当where标签中的if语句有条件成立时,就会动态的添加where关键字,还可以删除where后面紧跟着的关键字,例如and  or

<select id="teachers" resultType="com.lw.mybatispro.model.Teacher">
     select * from teacher
     <where>
         <if test="num!=null">
             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="teachers" resultType="com.lw.mybatispro.model.Teacher">
     select * from teacher
     <trim prefix="where" prefixOverrides="and|or">
         <if test="num!=null">
             num=#{num}
         </if>
         <if test="name!=null">
             or name=#{name}
         </if>
         <if test="gender!=null">
             and gender=#{gender}
         </if>
     </trim>
</select>

修改

    <update id="updateTeacher">
        update teacher
        <trim prefix="set" suffixOverrides=",">
            <if test="num!=null">
                num=#{num},
            </if>
            <if test="name!=null">
                name=#{name},
            </if>
            <if test="gender!=null">
                gender=#{gender}
            </if>
        </trim>
        where id = #{id}
    </update>
choose、when、otherwise标签

<choose>
     <when test="条件">     </when>
     <otherwise>     </otherwise>
</choose>

when、otherwise两个标签使用时类似于if else,可以只有when,但不能只有otherwise

<select id="teachers" resultType="com.lw.mybatispro.model.Teacher">
     select * from teacher
     <trim prefix="where" prefixOverrides="and|or">
         <choose>
             <when test="name!=null">
                 name=#{name}
             </when>
             <otherwise>
                 name="药老"
             </otherwise>
         </choose>
     </trim>
</select>
foreach标签

当参数是数组或者集合时使用,可以遍历出数组或集合中的内容

属性

item=" "

循环变量,在每次循环过程中代表集合中的一个元素。

collection=" array或list "

参数的类型,当参数是数组时为array,当参数是集合时为list

open="  "

标志着循环的开始,以引号中的内容为开始

separator="  "

每次循环时,加在两个循环之间,作为分隔符

close="  "

标志着循环的结束,结束时以引号中的内容为结尾

    <delete id="deleteTeacher">
        delete from teacher
        where id in
        <foreach item="id" collection="array" open="(" separator="," close=")">
            #{id}
        </foreach>
    </delete>

特殊符号处理

1.使用转义字符 

    <        &lt;

    >        &gt;

    "        &quot;

    ’         &apos;

    &        &amp;

2. 使用  <![CDATA[     ]]>标签

    <![CDATA[ ]]>是 XML 语法。在 CDATA 内部的所有内容都会被解析器忽略。    

    只把有特殊字符的语句放在 <![CDATA[ ]]>标签中

    例如    <![CDATA[ age<18 ]]>

xml(可扩展的标记语言) 作用:存储传输数据

缓存

    数据缓存,让数据离我们的执行程序更近,让程序能够快速的获取到数据

    手机缓存,浏览器缓存,cpu缓存……

    访问量大的时候,使用缓存将数据库的内容存到后端程序

    12306 访问瓶颈在数据库

    适合放入缓存的数据:访问量大的,经常不修改的

    有缓存,查询数据

    先从缓存中查数据,如果缓存中没有,去数据库查询,查询到后把数据放到缓存中,下次直接从缓存中获取

mybatis  一级缓存

        默认是SqlSession级别的,在同一个SqlSession中查询到数据先缓存到SqlSession对象中
                                第二次查询数据时,先从SqlSession中查询,如果有,直接返回,没有,再去数据库查询

一级缓存生命周期

开始于SqlSession创建

结束于SqlSession关闭

        如果期间执行了新增,修改,删除操纵,也会清空当前SqlSession对象中的数据

        调用sqlSession.clearCache(),会强制清空一级缓存数据

mybatis 二级缓存

二级缓存是SqlSessionFactory级别的,可以让多个SqlSession共享数据

        mybatis默认没有开启二级缓存,使用时需要配置开启        

        如果开启了二级缓存,当sqlSession关闭时,会将一级缓存中的数据存储到二级缓存中,其他SqlSession就可以在二级缓存中查询到之前sqlSession查询的数据

配置二级缓存配置
第一步:启用二级缓存

        在 SqlMapperConfig.xml 中启用二级缓存,如下代码所示,当cacheEnabled 设置为 true 时启用二级缓存,设置为 false 时禁用二级缓存。

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

第二步:对象序列化

            将所有的 POJO 类实现序列化接口 Java.io. Serializable。

第三步:配置映射文件

            在 Mapper 映射文件中添加<cache />,表示此 mapper 开启二级缓存。

            当 SqlSeesion 关闭时,会将数据存入到二级缓存.

useCache="true" 最小的开关 加在具体的执行语句的标签上

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值