Mybatis学习


前言

Mybatis学习以及自己的理解

一、mybaits是什么?

1.1 ORM

mybatis是一种ORM框架,ORM是Object Relational Mapping的缩写,中文翻译过来就是对象关系映射。对象就是java对象,指的是通过Java对象与数据库表之间的映射关系将Java应用程序中的对象持久化到数据库的表中。

1.2 Mybatis概述

MyBatis 是一个支持自定义 SQL存储过程以及高级映射的持久层框架

MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。

MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJO映射成数据库中的记录。

1.3 对Mybatis概述的理解

自定义 SQL:sql语句可以进行灵活的修改,在使用JDBC的时候,sql语句和java代码是融合在一起,mybatis是将sql语句和java代码分开来,sql代码写xml文件里,此时sql语句的修改会非常方便。

例如:如果给的要求是如下,sql 代码如下

mybatis代码:可以根据条件不同,动态的变化执行的sql语句。

select id,username,age,gender form t_user
<where>
		<if test="username != null and username != ''">
          AND username = #{userName, jdbcType=VARCHAR}
    </if>
</where>

存储过程:函数

高级映射:javabean和数据库对象的映射→输入映射和输出映射

输入参数映射:输入参数类型可以是 Map、List 等集合类型,也可以是基本数据类型和 POJO 类型。输入参数映射就是为sql语句提供参数的过程。下面的代码中#{id}就是提供输入映射。

输出结果映射:输出结果类型可以是 Map、 List 等集合类型,也可以是基本数据类型和 POJO 类型。输出映射对结果集进行封装的过程。下面的sql代码中,就是对查询出来的id,username,password,age,gender进行封装,比如下面的代码把这些结果封装在一个User对象里(resultType="com.form.User")。

<select id="selectUserById" resultType="com.form.User">
    select id,username,password,age.gender from t_user where id = #{id}
</select>

MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集:下面是JDBC操作数据库的代码,可以看出,执行sql代码前都要连接数据库,最后都要释放资源,这样会很影响系统性能,这样的JDBC代码最好避免。mybatis就是使用了数据库连接池,避免了资源的浪费。手动设置参数,先创建一个Statement对象来将SQL语句发送到数据,然后执行sql语句的查询,这个查询过程是手动设置的。结果集的获取也是手动设置的,代码如下。如果查询条件发生变化,就要改sql代码,修改获取结果集的代码。总之就是代码发生变化的时候,使用JDBC代码非常麻烦,不够灵活,而mybatis避免了这些问题。

public void testGetConnection1() throws SQLException { 

	// 注册驱动 

	Driver driver = new com.mysql.jdbc.Driver(); 

	// 建立连接 

	String url = "jdbc:mysql://localhost:3306/test"; 

	Properties info = new Properties(); 

	info.setProperty("user", "root"); 

	info.setProperty("password", "root"); 

	Connection con = driver.connect(url, info); //javaAPI,需要url和properties,得到连接对象
  
	// 获取SQL语句执行平台

	Statement stmt = con.createStatement(); //创建一个Statement对象来将SQL语句发送到数据库

	String sql = "select * from t where id = 1"; 

	// 执行SQL语句 

	ResultSet resultSet = stmt.executeQuery(sql); //查询

	// 处理结果 

	if (resultSet.next()) { 

		int id = resultSet.getInt(1); 

		int a = resultSet.getInt(2); 

		int b = resultSet.getInt(3); 

		int c = resultSet.getInt(4); 

		System.out.printf("%d, %d, %d, %d", id, a, b, c); 

}

	// 关闭连接,释放资源 

	con.close(); 

}

MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJO映射成数据库中的记录:

mybatis有两种书写方式,xml形式或者注解形式,平时用到的大多是xml形式。

xml形式:进行mybatis的配置,写上接口文件,再写上xml对应的文件。

接口文件:

@Repository
public interface BusinessProductDao {
    int insert(BusinessProduct record);
}

对应的xml文件:

    <insert id="insert" parameterType="com.formssi.third.dto.BusinessProduct">
    insert into business_product (product_id, product_name, state,belong_to_group
      )
    values (#{productId,jdbcType=VARCHAR}, #{productName,jdbcType=VARCHAR},
     #{state,jdbcType=VARCHAR},#{belongToGroup,jdbcType=VARCHAR}
      )
  </insert>

注解形式:用@Select, @Insert, @Update and @Delete在接口上声明增删查改方法,@Resluts与<reslutMap>的作用相同,用来获取结果,用了注解以后,就不用xml文件了。

package com.concretepage;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
public interface VillageMapper {
	@Results({
          @Result(property = "vid", column = "id"),
          @Result(property = "villageName", column = "name"),
          @Result(property = "district", column = "district")
        })
	@Select("SELECT id, name, district from village WHERE id = #{id}")
	Village selectVillage(int id);
	
	@Insert("INSERT into village(name,district) VALUES(#{villageName}, #{district})")
	void insertVillage(Village village);
	
	@Update("UPDATE village SET name=#{villageName}, district =#{district} WHERE id =#{vid}")
	void updateVillage(Village village);
	
	@Delete("DELETE FROM village WHERE id =#{id}")
	void deleteVillage(int id);
} 

MyBatis 3 Annotation Example with @Select, @Insert, @Update and @Delete

二、mybatis入门

1.引入mybatis的配置

用的springboot参考的文章:SpringBoot整合Mybatis完整详细版_海岛拾贝的博客-CSDN博客_springboot mybatis

mybatis的xml文件详解:

第一行是编码方式,

第二行是mybatis的约束配置,

第三行的<mapper>元素是配置文件的根元素,包含一个namespace属性,namespace属性为<mapper>元素指定了唯一的命名空间,通常会设置成“包名+SQL映射文件名”的形式,com.form.third.dao都是包名,BusinessGroupDao是BusinessGroupDao.java这个文件名。在同一个映射文件下id不能重复--->namespace+id是唯一的-->能找到唯一与之对应的sql语句。在不同的映射文件下,id可以重复,因为namespace不一样,仍然可以保持namespace+id的唯一性。

子元素<select>中的信息是用于执行查询操作的配置,其id属性是<select>元素在映射文件中的唯一标识,映射文件中的getListByPage和xml文件中的id里的getListByPage相对应。parameterType属性用于指定传入参数的类型,这里表示传递给执行SQL的是一个BusinessGroupDto对象类型的参数。resultType属性用于指定返回结果的类型,返回的也是BusinessGroupDto对象类型的参数。

持久层接口文件:

@Repository
public interface BusinessGroupDao {
    List<BusinessGroupDto> getListByPage(@Param("form") BusinessGroupDto businessGroup);
}

xml映射文件:

1<?xml version="1.0" encoding="UTF-8"?>
2<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
3<mapper namespace="com.form.third.dao.BusinessGroupDao">
4    <select id="getListByPage"  parameterType="com.form.third.dto.BusinessGroupDto" resultType="com.form.third.dto.BusinessGroupDto">
        select id,group_id,group_name,state from business_group
    </select>
</mapper>

mybatis的核心对象:

2.mybatis配置文件元素:

转义字符:xml文件,&要使用转义字符&amp;

空格:&nbsp;  

>: &gt  greater than

<: &lt   less than

1.<properties>元素:properties(属性)

(1)单项配置:放在同一个配置文件mybatis.xml里进行配置

(2)引入配置文件:经常改动的值放在db.properties,其余仍然是放在mybatis.xml里。

2.<settings>元素:<settings>元素主要用于改变MyBatis运行时的行为,例如开启二级缓存、开启延迟加载等。(未完。。。。。)

3.<typeAliases>元素:

3.1 typeAliases(类型别名)

3.2包扫描:com.cskaoyan.bean.User,因为是包目录下的javabean,别名就可以直接是User的小写形式user。

mybatis系统定义的别名:可以直接在xml中文件中用系统给的别名就行了。

参考文章:mybatis定义别名_转身未来的博客-CSDN博客_mybatis 别名

4.<typeHandler>元素

MyBatis在预处理语句(Prepared Statement)中设置一个参数或者从结果集(Resultset)中取出一个值时,都要对参数和结果集进行处理,将预处理语句中传入的参数从javaType(Java类型)转换为jdbcType(JDBC类型),或者从数据库取出结果时将jdbcType转换为javaType。

5.<plugins>元素

MyBatis允许在已映射语句执行过程中的某一点进行拦截调用(通过插件来实现),<plugins>元素的作用就是配置用户所开发的插件。

6.<environments>元素

<environments>元素用于在配置文件中对数据库进行配置。default里放的是默认的环境id。<environments>里可以有很多个<environment>,就是可以配置多种数据库,<environment>里的id定义的数据库的环境id。然后就是事务管理和数据源的配置。<transactionManager>元素用于配置事务管理,它的type属性用于指定事务管理的方式,即使用哪种事务管理器;<dataSource>元素用于配置数据源,它的type属性用于指定使用哪种数据源。

mybatis提供了三种数据源类型,UNPOOLED:在每一次请求时会打开一次连接和关闭一次连接,对数据库资源是一种浪费。 POOLED:使用数据库连接池,每次请求去池里取就行了,就不用每次都创建和关闭,可以快速地响应请求。 JNDI:为了可以在EJB或应用服务器等容器中使用。

7.<mappers>元素

在配置文件中,<mappers>元素用于指定MyBatis映射文件的位置。有四种引入的方式,但是现在开发比较常用的是接口引入的方式。

使用class属性引入接口的全路径名称的使用规则:

1)接口名称和映射文件名称除拓展名要完全相同。

2)接口和映射文件要放同一个目录下。

参考文章:MyBatis框架中,使用class属性引入接口的全路径名称的使用规则和例子_我有一根魔法棒的博客-CSDN博客

(如下图所示,AccountMapper接口和AccountMapper映射文件同名并且在同一级classpath目录下,编译以后就可以在target的classpath看到它们在同一级目录下)

接口文件和映射文件之间的关系:

1)1中指的是namesapce要写接口文件的全类名。

2)2中指的是xml映射文件中id是接口文件中方法名。

3.映射文件:

<select>元素

<insert>元素

 useGenerateKeys:

 selectKey:

数据库主键包括自增和非自增,有时候新增一条数据不仅仅知道成功就行了,后边的逻辑可能还需要这个新增的主键,这时候再查询数据库就有点耗时费力,我们可以采用selectKey来帮助我们获取新增的主键。

1. order为after

2.order为before

<update>元素和<delete>元素略。

4.mybatis的动态SQL

3.1<if>标签:<if>元素是常用的判断语句,主要用于实现某些简单的条件选择。在实际应用中,我们可能会通过多个条件来精确地查询某个数据。例如,要查找某个用户信息,可以通过姓名和职业来查找用户,也可以不填写职业,直接通过姓名来查找用户,还可以都不填写而查询出所有用户,此时姓名和职业就是非必需条件。类似于这种情况,在MyBatis中就可以通过<if>元素来实现。

<?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="com.form.third.dao.UserMapper">
    <!--if元素的使用-->
    <select id="findUserByNameAndJods" parameterType="com.form.third.dto.User" resultType="com.form.third.dto.User">
        select * from t_user where 1=1
        <if test="username != null and username != ''">
            and username = #{userName, jdbcType=VARCHAR}
        </if>
        <if test="jobs != null and jobs != ''">
            and jobs = #{jobs, jdbcType=VARCHAR}
        </if>
    </select>
</mapper>

使用<if>元素的test属性分别对username和jobs进行了非空判断(test属性多用于条件判断语句中,用于判断真假,大部分的场景中都是进行非空判断的,有时也需要判断字符串、数字和枚举等),如果传入的查询条件非空,就进行动态SQL组装。

if标签中的test写的是条件:

等于: ==

不等于: !=

大于:gt

小于:lt

大于等于:大于或等于 → 年龄≥15 → test=”age gt 15 or age == 15”

小于等于:小于或等于 → 年龄≤15 → test=“age lt 15 or age == 15”

and和or如何表达:and、or

字符串的比较:username等于songge → test=“username == ‘songge’

字符串的长度:username的长度大于5 → test=“username.length gt 5”

简而言之,使用<if>条件进行判断,如果传入的条件符合,就进行动态sql组装。test属性一般放条件判断语句。

3.2 <choose><when><otherwise>元素

<choose><when><otherwise> 标签组:也是一个用于条件判断的标签组,和<if>的不同之处在于条件从<choose>进入,去匹配<when>中的添加,一旦匹配马上结束;若到找不到匹配项,将执行<other>中的语句;可以理解为<if>是 && 关系 <choose>是 || 关系 ,从多个选择条件去选择一个条件进行搜索。MyBatis提供了choose 元素,按顺序判断when中的条件出否成立,如果有一个成立,则choose结束。当choose中所有when的条件都不满则时,则执行 otherwise中的sql。类似于Java 的switch 语句,choose为switch,when为case,otherwise则为default。  if是与(and)的关系,而choose是或(or)的关系。 

MyBatis-动态SQL的if、choose、when、otherwise、trim、where、set、foreach使用(各种标签详解), 以及实体间关系配置 - 雪洗中关村 - 博客园

使用了<choose>元素进行SQL拼接,若第一个<when>元素中的条件为真,则只动态组装第一个<when>元素内的SQL片段;否则继续向下判断第二个<when>元素中的条件是否为真,以此类推;若前面所有when元素中的条件都不为真,则只组装<otherwise>元素内的SQL片段。

3.3<where>元素

<where>元素会自动判断组合条件下拼装的SQL语句,只有<where>元素内的条件成立时,才会在拼接SQL中加入where关键字,否则将不会添加;即使where之后的内容有多余的“AND”或“OR”,<where>元素也会自动将它们去除。如下例,username为空的时候,where后面就多了一个and,<where>就会帮我们把那个多出来的and去掉了。

3.4<trim>元素

更新update:根据id更新一个user,user的哪个字段不为null,我们就更新哪个字段

prefix:在trim标签里面内容的最前面新增某个内容

suffix:在trim标签里面内容的最后面新增某个内容

prefixOverrides:如果最前面出现个啥,我们去掉它

suffixOverrides:如果最后面出现个啥,我们去掉它

参考文章:mybatis trim 、 prefix、prefixoverrides 、suffix 、sufflxoverrldes使用总结_fengcai0123的博客-CSDN博客_prefixoverride

3.5<set>元素

<set>元素主要用于更新操作,主要作用是在动态包含的SQL语句前输出一个SET关键字,并将SQL语句中最后一个多余的逗号去除。

<update id="insertUser" parameterType="java.lang.String" >
        update t_user
        <set>
            <if test="name != null and name.length() > 0">name = #{name},</if>
            <if test="gender != null and gender.length() > 0">gender = #{gender},</if>
        </set>
        where id = {#id}
</update>

update user set name='xxx' ,  gender='xx'   where  id='x' ,上面的代码里gender后面多了个逗号,<set>元素就可以把这个逗号去掉。

<set>标签也相当于:

参考文章:mybatis trim 、 prefix、prefixoverrides 、suffix 、sufflxoverrldes使用总结_fengcai0123的博客-CSDN博客_prefixoverride

3.6<foreach>元素

item:配置的是循环中当前的元素。 index:配置的是当前元素在集合中的位置下标。 collection:配置的list是传递过来的参数类型(首字母小写),可以是一个array、list(或collection)、Map集合的键、POJO包装类中的数组或集合类型的属性名等。 open和close:配置的是以什么符号将这些集合元素包装起来。 separator:配置的是各个元素的间隔符。

集合参数。当使用可迭代对象或者数组时,index是当前迭代的次数,item的值是本次迭代获取的元素。当使用字典(或者MapEntry对象的集合)时,index是键,item是值。

在使用<foreach>时,最关键、最容易出错的就是collection属性,该属性是必须指定的,而且在不同情况下该属性的值是不一样的,主要有以下3种情况。 如果传入的是单参数且参数类型是一个数组或者List的时候,collection属性值分别为array、list(或collection)。 如果传入的参数有多个,就需要把它们封装成一个Map,当然单参数也可以封装成Map集合,这时collection属性值就为Map的键。 如果传入的参数是POJO包装类,collection属性值就为该包装类中需要进行遍历的数组或集合的属性名。

3.7 sql include

把sql语句放到sql标签中,include标签就可以引用 → 把通用的sql语句提取出来,通过include标签进行引用。sql标签做了全局的sql片段,可以进行引用。

sql片段中也可以写其他的标签

5.Mybatis的关联映射

输入映射

5.1 没有注解

5.1.1 基本类型、包装类、String

5.1.2 javabean

5.1.3 map

5.1.4 多个参数

基本类型、包装类、String:param或arg

javabean或map:(param或arg) 加上(javabean的成员变量名或map的key)

接口中的方法上,可以在形参中写多个参数

param和arg对应的是第几个参数:

如果使用param:下标从1开始 → 对应第一个参数

如果使用arg:下标从0 → 对应第一个参数

5.1.5 使用注解

@Param中写了什么value,那么你在#{}中就用什么值。(不管你的参数类型是什么,不管你的参数有几个)

javabean → #{}中写@Param中的值+javabean的成员变量名

基本类型、包装类和String → #{}就用@Param中的value

map → #{}中写@Param中的值+map的key

输出映射

查询结果的封装 → 做的是查询select

select标签中resultType不能少,resultType始终写的是单条数据的类型

mybatis不管你接口中的方法返回值为单条还是多条数据,mybatis在底层接收查询结果的时候,都是先通过list来接收的,所以resultType大家直接写单条数据类型就可以了。

5.2 基本类型、包装类、String

查询user表中的记录数:

根据id查询username:

封装多条数据:数组或list接收

javabean的成员变量名和表的列名不一致,用as

多表映射:

user userDetail 一对一关系,在一个javabean中创建一个成员变量为另一个javabean类型

分次查询:

第一次查询查左表,第二次查询查右表,association或collection标签中,property:父标签javabean的成员变量名

column:查询结果的列名,并且为第二次查询提供参数,select:第二次查询的命名空间+id

用户和订单user和order存在一对多的关系,在左边的javabean中创建右多类型的list,在User中创建一个List<Order>。

多对多(本质上就是一对多)

课程和学生:多对多关系,一门课程对应多名学生,一名学生对应多门课程,互为一对多关系

在javabean中创建另一个javabean的list

Course中包含List<Student>

Student中包含List<Course>

6.1 setting 

6.1.1 缓存cache

执行一个查询,把查询结果记录下来,下一次执行相同的查询,就不会执行jdbc操作。

两级缓存:

               一级缓存:sqlSession级别,使用相同的sqlSession,默认开启的

               同一个sqlSession下执行相同的查询

              

             

               一级缓存何时失效?sqlSession进行commit则会清空一级缓存

              

               

                 

二级缓存:命名空间级别

需要做以下几步才能使用到二级缓存

  1. setting → cacheEnabled=true
  2. resultType对应的javabean要实现序列化 implements Serializable
  3. 映射文件中增加<cache/>

二级缓存我们不必要同一个sqlSession下去执行

需要通过commit放入二级缓存中

二级缓存何时失效?

当我们执行修改数据库中数据操作(insert、update、delete),通过提交sqlSession时会失效。

6.1.2 懒加载

当你去获得对象的时候才去执行查询。 → 输出映射的过程 → 分次查询

增加lazyLoadingEnabled之后,所有的分次查询均为懒加载了,我们想要立即加载,增加fetchType=eager

settings增加lazyLoadingEnabled=true
参考文章:

https://tudan.blog.csdn.net/article/details/104316949

SpringBoot整合Mybatis完整详细版_海岛拾贝的博客-CSDN博客_springboot mybatis

MyBatis 3 Annotation Example with @Select, @Insert, @Update and @Delete

参考图书:Spring + Spring MVC + Mybatis 从零开始学

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值