mybatis框架详解

简介: mybatis框架详解

一、简介

1、历史

mybatis的前身是apache ibatis,2010年由ASF转移到google code,从ibatis3.x改名为mybatis,2013年转移到github。mybatis是由java实现的持久层框架。

2、mybatis的特性

mybatis是一个半自动化的持久层框架,

可以注解配置、映射xml文件中编写动态sql语句。通常使用xml编写sql。

mybatis是对jdbc封装的框架,几乎不需要jdbc操作

mybatis提供面向接口编程,持久层只需要一个接口,不需要实现类。

3、和其他持久层框架 的比较

jdbc : 硬编码,在java语句中写sql,耦合度高

hibernate、jpa:自动框架,由框架生成sql语句,不需要人为编写,灵活度较差,高度定制化的sql语句需要跳过框架。

mybatis:半自动化的框架,可以注解配置、xml配置。


二、映射文件

1、mybatis的映射文件结构

<!DOCTYPE   mapper   ...>
<mapper   namespace="com.sly.ecs.business.mapper.mission.MissionMapper">
    <insert id="insertBatch"  parameterType="list"  ...> 
    <select id="selectMission"  parameterType="int" resultMap="BaseResultMap" ...>   
</mapper>

通过顶级标签中的namespace属性来指定对应的mapper接口,

通过子标签的id属性来指定对应的抽象方法。

2、参数

(1)传入参数的情形:

①、mapper接口方法的参数是单个:

xml文件用#{ },来取值,需要注意 { }来取值,需要注意来取值,需要注意{ }要用单引号。

{}中的名称是任意的,因为只有一个参数,无论取值时叫什么,都能够取到值。

②、mapper接口方法的参数是多个:

会用Map集合保存参数,键是由mybatis框架自动生成

1)xml文件可以用 arg0 、arg1 。。。 获取对应位置的参数

2)xml文件可以用 param1 、param2 。。。 获取对应位置的参数

也可以交叉使用,例如 arg0、 param2

③、mapper接口方法的参数是多个,可以放到一个Map集合里

键是由开发者人为设置。

在xml映射文件里根据人为设置的键获取参数。

例如:在600ly公司代码中使用 GenericQueryParam装载参数。

public final class GenericQueryParam extends LinkedHashMap<String, Object> 
                                implements ListQueryParam { ...  }
var param = new GenericQueryParam();
param.fill("signCode", signCode).fill("typeId", typeId).fill("labelId", labelId)
     .fill("areaId", areaId).fill("status", status).fill("userId", userId);

④、mapper接口方法的参数是实体类

xml文件里根据实体类的属性获取属性值。


补充知识:实体类中有set、get方法的才算做属性,不是按照全局变量来定义的。


⑤、mapper接口方法传入@Param注解参数

参数会保存到Map集合,以@Param的值作为键,xml文件以Map的键来获取参数。


归类:

①、参数加上@Param注解 传入方法

②、参数装进Map或者实体类 传入方法


(2)获取参数的两种方式:(jdbc原生写法)

${} 字符串拼接。不会带上单引号。注意要手动加上单引号。

#{} 占位符赋值。会带上单引号。不需要手动加上单引号。


示例:

①、常规


username = #{username}  AND sign_code = #{signCode}

②、Mybatis处理模糊查询

role_name LIKE CONCAT('%',#{roleName},'%')
role_name LIKE '%${roleName}%'
role_name LIKE "%"#{roleName}"%"

③、in范围查询:

String ids=“1,4,25”;

pk_id   IN  (${ids})


④、动态设置表名、字段名、排序关键字:

select   *   from   ${tableName}
ORDER   BY   ${sortColumn}  ${sortOrder}


总结:

  sql语法中需要引号的 尽量使用#{},或者${} 手动加上引号。 例如字符串、日期等类型的值。
  sql语法中不需要引号的 使用${} ,不用手动加上引号。例如in范围查询、表名、字段、排序关键字。

3、返回值

(1)增删改操作的返回值可以是void、int

int类型的返回值是sql语句影响的数据条数。

(2)查询操作的返回值在xml映射文件标签的属性resultType或resultMap里设置。

resultType是单个类型,resultMap是人为设置的字段-属性的映射关系。


select查询结果的情况:

①、如果查询的结果是一条记录

查询结果可以用实体类或者list 或者 map集合接收。

用map集合接收,查询结果的字段作为键,字段对应的值作为值。


②、如果查询的结果是多条记录

1)可以用List<> 接收。

List<实体类>或者 List<Map<String,Object>接收

不能用单个实体类接收多条记录。会报TooManyResultsException。

2)可以用一个map集合接收。

在@MapKey(“”) 注解的value属性中指定某个字段的值作为map的键。

例如:@MapKey(“id”)


③、查询结果是单行单列,可以用基本数据或String类型接收。


4、类型别名

Mybatis框架对常用的类型设置了对应的别名,用来替代全类名,简化代码。

简记:基本数据类型前面加下划线,复杂数据类型为全小写。

27.png28.png


5、添加操作,获取自增主键

User  u=new User(null,"yang","123456","男");
userMapper.insertUser(u);
u.getId();
int  insertUser(User  user);
<insert   id="insertUser"   useGeneratedKeys="true"   keyProperty="id">
    insert   into   t_user   values(null,#{username},#{password},#{sex} )
</insert>

useGeneratedKeys:设置当前的sql使用了自增的主键。

keyProperty:将自增的主键的值赋值给传输到映射文件中参数的某个属性。


6、解决字段名和属性名不一致的情况

1)在Mapper.xml文件里给sql语句的字段起别名

emp_name as empName

2)在mybatis配置文件设置 下划线转换为驼峰式。

<settings>
    <setting   name="mapUnderscoresToCamelCase"   value="true"/>
</settings>   

3)在Mapper.xml文件里设置结果映射

<resultMap    id="BaseResultMap"    type="User"  >
    <id   property="pkId"   colume="pk_id"/>
    <result   property="userName"   colume="user_name"/>
    <result   property="password"   colume="password"/>
    <result   property="sex"   colume="sex"/>
    <result   property="email"   colume="email"/>
</resultMap>

处理多对一 映射关系:

例:dept部门表和emp员工表是一对多的关系。在Emp实体类中加入Dept dept属性。

select  *  from  t_emp  t1  left  join  t_dept  t2  on  t1.did=t2.did


需要将查询结果字段装到Emp类中。

方式1:设置级联映射

<resultMap    id="empAndDeptMap"    type="Emp"  >
    <id   property="eid"   colume="eid"/>
    <result   property="empName"   colume="emp_name"/>
    <result   property="address"   colume="address"/>
    <result   property="sex"   colume="sex"/>
    <result   property="email"   colume="email"/>
    <result   property="dept.did"   colume="did"/>
    <result   property="dept.deptName"   colume="dept_name"/>
</resultMap>

方式2:association

<resultMap    id="empAndDeptMap"    type="Emp"  >
    <id   property="eid"   colume="eid"/>
    <result   property="empName"   colume="emp_name"/>
    <result   property="address"   colume="address"/>
    <result   property="sex"   colume="sex"/>
    <result   property="email"   colume="email"/>
    <association  property="dept"  javaType="Dept">
        <id   property="did"   colume="did"/>
        <result   property="deptName"   colume="dept_name"/>
    </association>
</resultMap>

方法3:分步查询

处理一对多 映射关系:


三、动态sql

1、where、 if 标签

if 标签:对标签中test属性的表达式 进行判断,为true则显示标签内的过滤条件,为false则不显示标签内的过滤条件。

where标签中 没有过滤条件,不加where关键字;

有过滤条件,加上where关键字,并将第一个条件前边的and 或者or 关键字删掉。

<select id="selectRoleByName" resultType="_int" parameterType="param">
  SELECT * FROM t_project_role
    <where>
        <if test="roleName != null and roleName != ''">
            AND role_name = #{roleName}
        </if>
        <if test="roleId != null and roleId != ''">
            AND pk_id != #{roleId}
        </if>
        <if test="roleType != null and roleType  != ''">
            OR role_type  = #{roleType}
        </if>
    </where>
</select>

如果 第2、3个if标签存在,则生成的动态sql是

SELECT * FROM t_project_role
where pk_id != #{roleId}  OR role_type = #{roleType}

2、trim 标签

有四个属性。

prefix,suffix:给trim标签里的内容加上前、后缀。

prefixoverrides,suffixoverrides:给trim标签里的内容 前或后 去掉内容。

<select id="selectRoleByName" resultType="_int" parameterType="param">
  SELECT * FROM t_project_role
    <trim  prefix="where"  suffixoverrides="AND|OR">
        <if test="roleName != null and roleName != ''">
            role_name = #{roleName} AND 
        </if>
    </trim>
</select>

生成的动态sql是

SELECT * FROM t_project_role
where  role_name != #{roleName }


3、choose、when、otherwise标签

相当于java语言中if…else if…else 条件判断代码块。


when 标签对test属性值进行判断,值为true则作为动态sql的条件,不再判断后面的条件。所以标签里的条件不需要加and或者or 。

值为false则判断后面的条件。如果when标签中的test 属性值都为false,则将otherwise标签作为条件。


when标签至少有一个,otherwise标签最多有一个。

<select id="findUserByChoose" parameterType="domain.User" resultType="domain.User">
    select * from USER
    <where>
        <choose>
            <when test="username!=null and username!=''">
                username=#{username}
            </when>
            <when test="sex!=null  and sex!=''">
                sex=#{sex}
            </when>
            <otherwise>
                did=1
            </otherwise>
        </choose>
    </where>
</select>

4、foreach 遍历集合、数组

(1)in 范围查找

DELETE FROM t_code
WHERE pk_id IN  
<foreach  collection="list"  item="pkId"  open="("  close=")"  separator="," >
    #{pkId}
</foreach>
DELETE FROM t_code
WHERE pk_id IN (12,23,55,86)

(2)批量添加

INSERT  INTO    t_user(pk_id, name, sex, age)    values
<foreach  collection="list"  item="user"  separator=",">
    ( null, #{user.username}, #{user.sex}, #{user.age} )
</foreach>

5、sql

写一些常用的sql块

例如:

<sql  id="Base_Column_List" >
    pk_id, code_class, code_name, sort, remark, create_user,
    create_date, update_user, update_date, is_valid
</sql>
<sql id="Base_Count">
   SELECT COUNT(0) FROM t_code
</sql>
<sql id="Base_Select">
   SELECT
   <include refid="Base_Column_List" />
   FROM t_code
</sql>
<sql id="Base_Where">
   <where>
      <if test="pkId != null and pkId != ''">
         AND pk_id = #{pkId}
      </if>
      <if test="codeClass != null and codeClass != ''">
         AND code_class = #{codeClass}
      </if>
      <if test="codeName != null and codeName != ''">
         AND code_name = #{codeName}
      </if>
      <if test="(sort != null and sort != '') or sort == 0">
         AND sort = #{sort}
      </if>
      <if test="remark != null and remark != ''">
         AND remark = #{remark}
      </if>
      <if test="(createUser != null and createUser != '') or createUser == 0">
         AND create_user = #{createUser}
      </if>
      <if test="createDate != null">
         AND create_date = #{createDate}
      </if>
      <if test="(updateUser != null and updateUser != '') or updateUser == 0">
         AND update_user = #{updateUser}
      </if>
      <if test="updateDate != null">
         AND update_date = #{updateDate}
      </if>
      <if test="(isValid != null and isValid != '') or isValid == 0">
         AND is_valid = #{isValid}
      </if>
   </where>
</sql>
<sql id="Base_Sort">
   <if test="_parameter.getSortParam().size() > 0">
      ORDER BY
      <foreach collection="_parameter.getSortParam()"
         item="sortParam" separator=",">
         ${sortParam.column} ${sortParam.order}
      </foreach>
   </if>
</sql>
<sql id="Base_Page">
   <if test="isPage == 1">
      LIMIT #{_offset}, #{_pagesize}
   </if>
</sql>

四、mybatis缓存

1、一级缓存

使用同一个SqlSession,根据相同的查询条件,只在第一次查询时执行sql语句,之后每次查询,都使用mybatis缓存的结果数据。

一级缓存失效的情形:

(1)不同的SqlSession对应不同的一级缓存

(2)同一个SqlSession ,查询条件不同

(3)同一个SqlSession ,两次查询之间有增删改操作

(4)同一个SqlSession ,两次查询之间清理过缓存clearCache()


2、二级缓存

使用同一个SqlSessionFactory,只在第一次查询时执行sql语句,之后每次查询,都是用mybatis二级缓存。


二级缓存开启的条件:

(1)在核心配置文件中加上cacheEnabled="true"全局属性

(2)在映射文件加上 标签

(3)在两次查询之间,对SqlSession 进行commit()或close()

(4)查询结果转换的实体类型要实现序列化接口。


失效的情形:在两次查询之间,执行任意的增删改操作,一级和二级缓存都会失效。

3、mybatis缓存的查询顺序

(1)先在二级缓存中查找

(2)二级缓存没有,则在一级缓存中查找

(3)一级缓存中没有,则到数据库中查找

(4)SqlSession关闭之后,一级缓存中的数据保存到二级缓存中。


mybatis是持久层框架,做缓存功能不是很擅长,有开放的接口可以使用第三方缓存工具。只能替代mybatis的二级缓存。例如EHCache。


五、mybatis逆向工程

正向工程:根据实体类 生成数据库表。例如Hibernate框架

逆向工程:根据数据库表生成实体类、映射文件、mapper接口。

mybatis的逆向工程分为简易版和全面版。

简易版包括五个增删改查方法。其中查询方法包括查询全部和根据id查找。

相关文章
|
SQL Java 数据库连接
MyBatis 优秀的持久层框架(一)
MyBatis 优秀的持久层框架
66 0
|
1月前
|
SQL 关系型数据库 Java
Mybatis-Flex框架初体验
Mybatis-Flex框架初体验
|
2月前
|
SQL Java 数据库连接
|
3月前
|
SQL Java 数据库连接
JAVAEE框架技术之7-myBatis ORM框架入门基础CRUD
JAVAEE框架技术之7-myBatis ORM框架入门基础CRUD
90 0
JAVAEE框架技术之7-myBatis ORM框架入门基础CRUD
|
3月前
|
Java 数据库连接 Maven
SSM框架整合:掌握Spring+Spring MVC+MyBatis的完美结合!
SSM框架整合:掌握Spring+Spring MVC+MyBatis的完美结合!
|
3月前
|
Java 数据库 数据安全/隐私保护
基于SSM框架实现管科类考研自我管理系统(分前后台spring+springmvc+mybatis+maven+jsp+jquery)
基于SSM框架实现管科类考研自我管理系统(分前后台spring+springmvc+mybatis+maven+jsp+jquery)
|
3月前
|
Java BI 数据库
基于SSM框架实现面向小微企业的简历管理系统企业简历管理系统(分前后台spring+springmvc+mybatis+maven+jsp+css+echarts)
基于SSM框架实现面向小微企业的简历管理系统企业简历管理系统(分前后台spring+springmvc+mybatis+maven+jsp+css+echarts)
|
13天前
|
SQL Java 数据库连接
什么是MyBatis持久层框架?
MyBatis 是一个优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs (Plain Old Java Objects, 普通的 Java 对象) 映射成数据库中的记录。
26 5
|
29天前
|
SQL XML Java
这样使用MyBatis框架,被攻击了
这样使用MyBatis框架,被攻击了
14 0
|
30天前
|
Java fastjson Apache
Spring Boot+Gradle+ MyBatisPlus3.x搭建企业级的后台分离框架
Spring Boot+Gradle+ MyBatisPlus3.x搭建企业级的后台分离框架
31 1