java框架第一课(mybatis认识)

一.关于mybatis

1.mybatis的背景

mybatis原来 是Apache的一个开源项目iBatis,2010年6月这个项目由ApacheSoftware Foundation 迁移到了 Google Code,并改名为mybatis。

2.mybitis的介绍

(1)MyBatis 是一款优秀的持久层框架(在与数据库交互,数据访问层,数据持久层)。(mybatis对jdbc进行包装)
(2)MyBatis 避免了几乎所有的 JDBC 代码手动设置参数以及手动获取结果集的操作。
(3)MyBatis将jdbc中的接口进行封装使用自己定义的接口和类来实现。
(4)MyBatis可以使用xml文件配置和注解的方式,将数据库中记录的数据自动映射到java的对象中。是一种 ORM(ORMObject Relational Mapping 对象关系映射)实现,它支持动态 SQL(包含逻辑判断的sql语句) 以及数据缓存。az
(5)Mybatis 中文官网
https://mybatis.org/mybatis-3/zh_CN/index.html

3.Mybatis的搭建

(1)Mybatis作为对jdbc包装的框架,需要使用MAVEN,所以首先需要确保java有Maven,然后创建一个Maven的java工程,在pom.xml文件中配置 MyBatis jar 包要 **连接数据库有关的依赖(**这里以mysql)为例。

复制代码
<!--mysql的依赖--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.16</version> </dependency>

<!--junit的依赖--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.2</version> </dependency>

(2)创建 MyBatis 全局配置文件(核心)

首先需要在创建的Maven的resources中创建一个xml文件,在这个xml文件中配置与数据库jdbc连接有关的数据库账号密码等,类似于jdbc的加载驱动,建立连接等。

(3)定义接口

由于Mybatis对jdbc进行了封装,所以与数据库交互时直接创建接口,在接口中定义方法(数据库要执行的增删改查语句)。

java 复制代码
public interface Admindao {
    Admin findAdminById(int id);
    void deleteAdminById(int id);
    void insertAdminById(Admin admin);
    void updateAdminById(Admin admin);
    void deleteAdmidById(int id);
    List<Admin> selectAdminById();
}

(4)创建sql映射文件

mybatis用接口和类封装了jdbc,所以与jdbc的sql语句有关的代码写在sql映射文件中

java 复制代码
<?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="接口的地址">
<select id="findAdminById" parameterType="int" resultType="com.ffyc.mybatis.model.Admin">
select * from admin where id = #{id} </select> </mapper>

最后别忘了在resources下面的xml文件中(全局配置文件中)注册映射文件

sql映射文件最终结果(如下图)

二.关于mybatis中sql语句

(1)单值表达式

1.例如在admin(用户表中)查找用户id为1的用户信息,由于在自定义接口的方法中传入的参数只有一个类型为Int的id,称此表达式(传入的参数只有一个)为mybatis中的单值表达式。如下代码所示

java 复制代码
public interface Admindao {
    Admin findAdminById(int id);
}

2.在接口中定义好方法后,在sql映射文件中首先配置该接口的地址,然后在配置与要写的sql语句(增删改查)有关的参数类型,返回值类型,等信息。(如配置查找用户id为1用户信息)

java 复制代码
    <select id="findAdminById" parameterType="int" resultType="Admin">
select * from admin where id = #{id}
</select>

3.配置好后在新建类的Main方法中使用Mybatis,按照先加载数据库,然后创建SqlSessionFactory,然后创建接口代理对象,最后获得代理对象,使用代理对象找到接口中定义的方法(增删改查)

java 复制代码
      //1。读取配置文件,加载mysql
        Reader reader = Resources.getResourceAsReader("mybatis.xml");
        //2。创建 SqlSessionFactory,连接数据库会话对象类似connection
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
        //3.创建接口代理对象·
        SqlSession sqlSession = sessionFactory.openSession();
        //获得接口代理对象
     Admindao mybatis= sqlSession.getMapper(Admindao.class);
     Admin admin=mybatis.findAdminById(1);//让代理对象调用映射文件中于此接口中相同名称的方法
                 mybatis.deleteAdminById(1);
        System.out.println(admin);
        sqlSession .close();//关闭与数据库的连接对象

单表的增删改查

增删改查
<insert id="唯一标识" useGeneratedKeys="把新增加的主键赋值到自己定义的
keyProperty " keyProperty=" 接收主键的属性 parameterType="参数类型">insert into
admin(account,password)values(#{account},#{password})
</insert>
</mapper>
修改
<update id="唯一标识" parameterType="参数类型">
update
admin set account= #{account},password= #{password} where
id= #{id}
</update>
删除
<delete id="唯一标识" parameterType="参数类型">
delete from admin where id= #{id}
</delete>
查询
<select id="唯一标识" resultType="返回结果集类型">
select *
from admin where id= #{id}
</select>

三.关于对象映射

(1)简单的单表对象映射

如果数据库中表的的类名与类中的属性名完全相同,mybatis会自动将查询结果封装
到POJO对象中,否则需要自定义映射,将表中查询的结果映射到自定义的类中(以管理员表为例),管理员表有id,accountf(账号),password(密码)



在xml文件中,由于查询语句的id名与管理员的类中属性名不一样,所以就要给这个查询语句起别名(改为与管理员类中属性名一样)或者自定义映射,以自定义映射为例

(1). resutlMap 的 id 属性是 resutlMap 的唯一标识,本例中定义为
"adminMap"
(2). resutlMap 的 type 属性是映射的 POJO 类型
(3). id 标签映射主键,result 标签映射非主键
(4). property 设置对象属性名称,column 映射查询结果的列名称

java 复制代码
    <!--type返回值类型,id主键,resultMap自定义映射-->
   <resultMap id="adminMap" type="Admin">
     <id column="adminid" property="id"></id>
       <result column="account" property="account"></result>
       <result column="gender" property="gender"></result>
    </resultMap>
    <select id="selectAdminById" resultMap="adminMap">
        select adminid,account,gender from admin
    </select>

(2)复杂的多表对象映射

当用Mybatis查询的结果关联多个表时,此时就需要用到关联或者嵌套查询。(以学生选专业为例,牵扯到两张表,此时就需要学生关联专业。(需要用到resultMap 元素中 association , collection 元素. )

1.关联查询(联合表查)

java 复制代码
    <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>
        <!--association关联表用-->
        <association property="major" javaType="Major">
          <result column="mname" property="name"></result>
        </association>
    </resultMap>
    <!--方式一关联查询-->
    <select id="selectstudent" parameterType="int" 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.嵌套查询(分开查表)( 将一个多表关联查询拆分为多次查询,先查询主表数据,然后查询关联表数据.)

<association
property="dept"
javaType="Dept"
select="findDeptByID" column="dept_id"></association>
(1). select:指定关联查询对象的 Mapper Statement ID 为 findDeptByID
(2). column="dept_id":关联查询时将 dept_id 列的值传入 findDeptByID,
并将 findDeptByID 查询的结果映射到 Emp 的 dept 属性中
(3).collection 和 association 都需要配置 select 和 column 属性,两者配置方法
相同

java 复制代码
    <!--方式二嵌套查询,先查主表(学生表)-->
    <resultMap id="studentsmap" 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>
        <!--select="findmajorid" 将查到的majorid赋给column="majorid"-->
       <association property="major" javaType="Major" select="findmajorid" column="majorid">

       </association>
    </resultMap>

    <select id="selectstudents" resultMap="studentsmap">
    select s.id,s.num,s.name,s.gender,m.name mname,s.majorid
from student s inner join major m on s.majorid=m.id
    </select>

    <select id="findmajorid" resultType="Major">
        select name from major where id=#{majorid}
    </select>
四.sql映射文件中关于书写sql时#{} 和${}区别

(1)#{} 占位符,是经过预编译的,编译好 SQL 语句再取值,#方式能够防止 sql 注入.

例如:#{}:delete from admin where id=#{id}(与jdbc中的用?占位控制符一样).
结果: delete from admin where id = ?
#{} 占位符经常用
(2){}会将将值以字符串形式拼接到 sql 语句, { }方式无法防止 Sql 注入
{}: delete from admin where id='{id}'
结果: delete from admin where id='1'
一般是#{ } 向 sql 传值使用, 而使用{ }向 sql 传列名 例如在 order by {column} 语句后面可以动态替换列名
一般在根据选择查询结果时使用,例如查询学生信息时选择学生的姓名,学号查询学生信息

五.Mybatis 动态 SQL

(1)什么是Mybatis 动态 SQL?
MyBatis 的一个强大的特性之一通常是它的动态 SQL 能力。 如果你有使用
JDBC 或其他 相似框架的经验,你就明白条件地串联 SQL 字符串在一起是多么
的痛苦,确保不能忘了空格或在列表的最后省略逗号。动态 SQL 可以彻底处理
这种痛苦。(简单来说动态sql就是在写sql语句时遇到的逻辑判断,例如:多个人对一张表的数据进行修改,这张表的数据那一部分这个人修改,哪一部分另一个人修改,都需要在sal的修改语句中做出判断)

(2)MyBatis 中用于实现动态 SQL 的元素主要有: (1)If
(2)where
(3)trim
(4)set
(5)choose (when, otherwise)
(6)foreach

if:if 标签可以对传入的条件进行判断
java 复制代码
    <update id="updateteacher" parameterType="Teacher">
     update teacher
     <trim prefix="set" prefixOverrides=",">
     <if test="name!=null">
         name=#{name}
     </if>
     <if test="num!=null">
       num=#{num}
      </if>
      <if test="gender!=null">
          gender=#{gender}
      </if>
     </trim>

     where id=#{id}
    </update>
java 复制代码
   /*where 标签当where标签If 语句有条件成立时,就会动态添加where 关键字*/

/*where>元素会进行判断,如果它包含的标签中有返回值的话,它就插入一个
        'where'。
        此外,如果标签返回的内容是以 AND 或 OR 开头,它会剔除掉 AND 或 OR。*/
<!--
   <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>
java 复制代码
    <!--item 表示集合中每一个元素进行迭代时的别名,index 指定一个名字,用于
表示在迭代过程中,每次迭代到的位置,open 表示该语句以什么开始,
separator 表示在每次进行迭代之间以什么符号作为分隔符,close 表示以什
么结束,在使用 foreach 的时候最关键的也是最容易出错的就是 collection
属性,该属性是必须指定的,但是在不同情况下,该属性的值是不一样的。
-- 如果传入的是单参数且参数类型是一个 List 的时候,collection 属
性值为 list -- 如果传入的是单参数且参数类型是一个 array 数组的时候,
collection 的属性值为
array-->
<!--
   <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>
-->
java 复制代码
/*有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句*/
<!--
<trim prefix="where" prefixOverrides="and|or">
    <choose >
     <when test="name!=null">
       name=#{name}
     </when>

    <otherwise>
        name='李老师'
    </otherwise>
    </choose>
</trim>
-->
java 复制代码
   <update id="updateteacher" parameterType="Teacher">
     update teacher
     <trim prefix="set" prefixOverrides=",">
     <if test="name!=null">
         name=#{name}
     </if>
     <if test="num!=null">
       num=#{num}
      </if>
      <if test="gender!=null">
          gender=#{gender}
      </if>
     </trim>

     where id=#{id}
    </update>
java 复制代码
   <delete id="deleteteacher">
    delete   from teacher where id in 
    <foreach collection="array" item="id" open="(" separator="," close=")">
        #{id}
    </foreach>

    </delete>

    <select id="teachers" resultType="Teacher" parameterType="Teacher">
 //  select *from teacher
6.缓存
(1)什么是缓存

缓存(cache)的作用是为了减去数据库的压力,提高查询性能。缓存实现的
原理是从数据库中查询出来的对象在使用完后不要销毁,而是存储在内存(缓存)
中,当再次需要获取该对象时,直接从内存(缓存)中直接获取,不再向数据库
执行 select 语句,从而减少了对数据库的查询次数,因此提高了数据库的性能。

(2)一级缓存和二级缓存

一级缓存:
Mybatis 对缓存提供支持,但是在没有配置的默认情况下,它只开启一级缓
存,一级缓存只是相对于同一个 SqlSession 而言。
所以在参数和 SQL 完全一样的情况下,我们使用同一个 SqlSession 对象调
用一个 Mapper 方法,往往只执行一次 SQL,因为使用 SelSession 第一次查询
后,MyBatis 会将其放在缓存中,以后再查询的时候,如果没有声明需要刷新,
并且缓存没有超时的情况下,SqlSession 都会取出当前缓存的数据,而不会再
次发送 SQL 到数据库。
二级缓存:
二级缓存是 SqlSessionFactory 级别的,根据 mapper 的 namespace 划分
区域的,相同 namespace 的 mapper 查询的数据缓存在同一个区域,如果使
用 mapper 代理方法每个 mapper 的 namespace 都不同,此时可以理解为二
级缓存区域是根据 mapper 划分。
每次查询会先从缓存区域查找,如果找不到则从数据库查询,并将查询到数
据写入缓存。Mybatis 内部存储缓存使用一个 HashMap,key 为
hashCode+sqlId+Sql 语句。value 为从查询出来映射生成的 java 对象。

相关推荐
Scott9999HH2 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
腻害兔2 小时前
【若依项目-产品经理视角】深度拆解 RuoYi-Vue-Pro 商城模块:从商品管理到交易引擎,50 张表撑起一整套电商系统
java·大数据·vue.js·产品经理·ai编程
码智社3 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海3 小时前
python 列表、元组、集合和字典
开发语言·python
萧瑟余晖4 小时前
JDK 26 新特性详解
java·开发语言
马优晨4 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
人邮异步社区6 小时前
怎么把C语言学到精通?
c语言·开发语言
心平气和量大福大7 小时前
C#-WPF-控件-TextBox 数据绑定
开发语言·c#·wpf
ttwuai7 小时前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang
维天说7 小时前
CLI-Switch 2026年3月版历史设计:Hook、TTY 隔离与 JSON 状态
java·服务器·json