百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

一文带你搞定mybatis的映射配置文件

mhr18 2024-10-20 06:49 35 浏览 0 评论

Mybatis映射文件

增删改查

简单地增删改查

<select id="selectUser" resultType="User">
    select * from `user` where id = #{id}
</select>

<insert id="addUser">
    insert into `user` (`name`,account) values (#{name},#{account})
</insert>

<update id="updateUser">
    update `user` set `name` = #{name}, account = #{account} where id = #{id}
</update>

<delete id="deleteUser">
    delete from `user` where id = #{id}
</delete>

使用factory.openSession()得到的sqlSession默认不会自动提交,需要手动的提交事务

使用factory.openSession(true)得到的sqlSession自动提交

select详细属性

<!-- 
    id 命名空间的唯一标识,一般为方法名
  parameterType   入参类型,该参数可选,mybatis通过类型处理器TypeHandler推断出具体传入的参数
  resultType      返回结果的类全限定名或别名(如果为集合,应设置为集合包含的类型,而不是集合本身的类型)
    resultMap       结果映射(resultType和ResultMap只能同时使用一个)
  flushCache      设置为true,该语句被调用后清空本地缓存和二级缓存,默认false
  useCache        设置为true,该语句结果被二级缓存缓存    select语句默认true
    timeout         等待数据库返回的超时时间
  fetchSize       批量返回的行数
  statementType   可选STATEMENT/PREPARED/CALLABLE  分别对应于Statement/PreparedStatement/CallaleStatement   默认PREPARED
  resultSetType   FORWARD_ONLY/SCROLL_SENSITIVE/SCROLL_INSENSITIVE/DEFAULT
  databaseId      数据库厂商id
  resultOrdered   只针对于嵌套结果select语句:如果为true,将会假设包含了嵌套结果集或是分组,当返回一个主结果行时,就不会产生对前面结果集的引用  默认false
  resultSets      针对于多结果集的情况。将列出语句执行后返回的结果集并赋予每个结果集一个名称,多个名称逗号隔开
-->
<select
  id="selectUser"    
  parameterType="int"
  resultType="hashmap"
  resultMap="personResultMap"
  flushCache="false"
  useCache="true"
  timeout="10"
  fetchSize="256"
  statementType="PREPARED"
  resultSetType="FORWARD_ONLY">

insert/update/delete详细属性

<!-- 
    id 命名空间的唯一标识,一般为方法名
  parameterType   入参类型,该参数可选,mybatis通过类型处理器TypeHandler推断出具体传入的参数
  flushCache      设置为true,该语句被调用后清空本地缓存和二级缓存, insert、update、delete语句默认false
    timeout         等待数据库返回的超时时间
  statementType   可选STATEMENT/PREPARED/CALLABLE  分别对应于Statement/PreparedStatement/CallaleStatement   默认PREPARED
  databaseId      数据库厂商id
  useGeneratedKeys  使用JDBC的getGeneratedKeys方法来获取数据库生成的主键,默认false
  keyProperty     指定对象的主键属性,将getGeneratedKeys的返回值赋给该属性,如果生成列不止一个,使用逗号隔开
  keyColumn       指定生成键值在数据库中的列名,如果生成列不止一个,用逗号隔开
-->

<insert
  id="insertAuthor"
  parameterType="domain.blog.Author"
  flushCache="true"
  statementType="PREPARED"
  keyProperty=""
  keyColumn=""
  useGeneratedKeys=""
  timeout="20">

  <update
  id="updateAuthor"
  parameterType="domain.blog.Author"
  flushCache="true"
  statementType="PREPARED"
  timeout="20">

  <delete
  id="deleteAuthor"
  parameterType="domain.blog.Author"
  flushCache="true"
  statementType="PREPARED"
  timeout="20">

插入扩展

获取自增id

默认情况下,插入数据后无法获取自增属性的主键id

<!--
    自增主键,mybatis利用statement.getGeneratedKeys()来获取
    useGeneratedKeys="true" 使用自增主键获取主键值策略
    keyProperty  指定对应的主键属性,mybatis获取到主键值后,将值赋给该属性
 -->
<insert id="addUserReturnGeneratedKey" useGeneratedKeys="true" keyProperty="id">
    insert into `user` (`name`,account) values (#{name},#{account})
</insert>

不支持自增主键的方式

<!--
    不支持自增主键的方式
 -->
<insert id="addUserReturnGeneratedKey" databaseId="oracle">
    <!-- 使用selectKey来获取主键序列值
        keyProperty 指定对应的主键属性,mybatis获取到主键值后,将值赋给该属性
        order before表示当前sql在插入sql之前
              after表示当前sql在插入sql之后
        resultType 查出来的数据返回值类型
     -->
    <selectKey keyProperty="id" order="BEFORE" resultType="Integer">
        select user_seq.nextval from dual
    </selectKey>
    insert into `user` (id,`name`,account) values (#{id},#{name},#{account})
</insert>

参数处理

普通的数据类型

User selectUserByIdAndName(@Param("id") int id,@Param("name") String name);
<!-- 测试多个参数取值
    mybatis默认将多个参数封装为一个map
         map的key为param1~paramN
         map的value为传入的参数值
         #{}使用的是map的key来取值
     可以使用命名参数来明确指定封装成map时的key @Param("id") @Param("name")
        map的key为@Param注解指定的名称
        map的value为传入的参数值
 -->
<select id="selectUserByIdAndName" resultType="User">
    select * from user where id = #{id} and name = #{name}
</select>

自定义的java对象数据类型

对于很多入参的情况,不希望方法的入参那么多,而且需要指定@Param参数,可以将这些入参封装为一个对象.

对于对象,可以直接使用字段来进行获取

User selectUserByCondition(User user);
<select id="selectUserByCondition" resultType="User">
        select * from user
        <where>
            <if test="id != null and id != 0">
              and id = #{id}
            </if>
            <if test="name != null">
                and name = #{name}
            </if>
            <if test="account != null and account != 0">
                and account = #{account}
            </if>
        </where>
    </select>

集合属性

对于List,mybatis会映射为list,可以通过list来获取集合中的值

List<User> selectByIds(List<Integer> ids);
<select id="selectByIds" resultType="User">
    select * from user
    <where>
        id in
        <foreach collection="list" index="index" item="item" open="(" separator="," close=")">
            #{item}
        </foreach>
    </where>
</select>

结果映射

resultMap和resultType都是作为结果集返回映射

ResultType

使用map

很多情况下使用map作为返回是可以支持的,但是map不是一个很好的领域模型,在获取到数据库结果之后,还需要再去人工的从map中取值给业务需要的字段去赋值,是一件痛苦而繁琐的事情

<select id="selectUser" resultType="map">
  select * from user where id = #{id}
</select>

使用PO

使用PO进行接收结果集时,考虑到数据库中的列名可能与po中的字段名不一致,需要为每个字段起别名,sql写起来就变长了很多

<select id="selectUser" resultType="User">
  select user_id as id,user_name as userName,
  from user where id = #{id}
</select>

ResultMap

由于在使用ResultType时有一些的问题,而且ResultType对于一些复杂的查询结果来说处理起来也并不友好,ResultMap自定义映射的好处就凸显出来了。

<resultMap id="user" type="com.zhanghe.study.mybatis.model.User">
    <!--
         id定义主键
             column 指定数据库的列名
             property 指定java的属性名
     -->
    <id column="id" property="id"/>
    <!-- 普通的列 -->
    <result column="name" property="name"/>
    <result column="account" property="account"/>
</resultMap>

 <select id="selectUserReturnResultMap" resultMap="user">
     select * from `user` where id = #{id}
 </select>

关联查询一对一

public class Employee {
    private Integer id;
    private String name;
    private double salary;
    private Department department;
}

public class Department {
    private Integer id;
    private String name;
}

级联属性封装

<!-- 级联查询 -->
<resultMap id="emp1" type="com.zhanghe.study.mybatis.model.Employee">
    <id column="id" property="id"/>
    <result column="name" property="name"/>
    <result column="salary" property="salary"/>
      <!-- 使用属性.属性来获取 -->
    <result column="did" property="department.id"/>
    <result column="dname" property="department.name"/>
</resultMap>

<select id="getEmpAndDep" resultMap="emp1">
    select emp.id id,emp.name name,emp.salary salary,emp.dep_id did,dep.name dname from employee emp join department dep on  emp.dep_id = dep.id
    where emp.id = #{id}
</select>

使用association进行join查询

<resultMap id="emp2" type="com.zhanghe.study.mybatis.model.Employee">
    <id column="id" property="id"/>
    <result column="name" property="name"/>
    <result column="salary" property="salary"/>
    <!-- 指定该字段的类型 -->
    <association property="department" javaType="com.zhanghe.study.mybatis.model.Department">
        <id column="did" property="id"/>
        <result column="dname" property="name"/>
    </association>
</resultMap>

<select id="getEmpAndDep" resultMap="emp2">
        select emp.id id,emp.name name,emp.salary salary,emp.dep_id did,dep.name dname from employee emp join department dep on  emp.dep_id = dep.id
        where emp.id = #{id}
</select>

使用association进行分步查询

使用分步查询会执行多条sql语句,先查询出主表,之后将关联列作为条件去查询字表信息

EmployeeMapper的映射文件

<resultMap id="emp3" type="com.zhanghe.study.mybatis.model.Employee">
    <id column="id" property="id"/>
    <result column="name" property="name"/>
    <result column="salary" property="salary"/>
    <!-- select 当前属性使用select调用的方法
         column 指定将那一列的值作为参数传入select语句
        -->
    <association property="department" column="dep_id"
                 select="com.zhanghe.study.mybatis.mapper.DepartmentMapper.selectDepById">
        <id column="did" property="id"/>
        <result column="dname" property="name"/>
    </association>
</resultMap>

<select id="getEmpAndDep" resultMap="emp3">
      select * from employee where id = #{id}
</select>

DepartmentMapper的映射文件

<resultMap id="dep" type="com.zhanghe.study.mybatis.model.Department">
    <id column="id" property="id"/>
    <result column="name" property="name"/>
</resultMap>

<select id="selectDepById" resultMap="dep">
    select * from department where id = #{id}
</select>

分步查询延迟加载

在使用子表信息的时候在进行查询

在全局配置中开启延迟加载

<settings>
  <setting name="logImpl" value="STDOUT_LOGGING"/>
  <!-- 延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置 fetchType 属性来覆盖该项的开关状态。 -->
  <setting name="lazyLoadingEnabled" value="true"/>
  <!-- 开启时,任一方法的调用都会加载该对象的所有延迟加载属性。 否则,每个延迟加载属性会按需加载 -->
  <setting name="aggressiveLazyLoading" value="false"/>
</settings>

关联查询一对多

使用collection标签

DepartmentMapper的映射文件

<resultMap id="dep1" type="com.zhanghe.study.mybatis.model.Department">
  <id column="id" property="id"/>
  <result column="name" property="name"/>
  <!-- select 当前属性使用select调用的方法
         column 指定将那一列的值作为参数传入select语句(如果需要多个条件使用{key1=value1,key2=value2})
        -->
  <collection property="employeeList" select="com.zhanghe.study.mybatis.mapper.EmployeeMapper.getEmployeeByDid"
              column="id">
    <id column="id" property="id"/>
    <result column="name" property="name"/>
    <result column="salary" property="salary"/>
    <result column="did" property="department.id"/>
  </collection>
</resultMap>

<select id="getDepAndEmps" resultMap="dep1">
    select * from department where id = #{id}
</select>

EmployeeMapper的映射文件

<resultMap id="emp" type="com.zhanghe.study.mybatis.model.Employee">
    <id column="id" property="id"/>
    <result column="name" property="name"/>
    <result column="salary" property="salary"/>
</resultMap>

<select id="getEmployeeByDid" resultMap="emp">
    select * from employee where dep_id = #{did}
</select>

相关推荐

【预警通报】关于WebLogic存在远程代码执行高危漏洞的预警通报

近日,Oracle官方发布了2021年1月关键补丁更新公告CPU(CriticalPatchUpdate),共修复了包括CVE-2021-2109(WeblogicServer远程代码执行漏洞)...

医院信息系统突发应急演练记录(医院信息化应急演练)

信息系统突发事件应急预案演练记录演练内容信息系统突发事件应急预案演练参与人员信息科参与科室:全院各部门日期xxxx-xx-xx时间20:00至24:00地点信息科记录:xxx1、...

一文掌握怎么利用Shell+Python实现完美版的多数据源备份程序

简介:在当今数字化时代,无论是企业还是个人,数据的安全性和业务的连续性都是至关重要的。数据一旦丢失,可能会造成无法估量的损失。因此,如何有效地对分布在不同位置的数据进行备份,尤其是异地备份,成为了一个...

docker搭建系统环境(docker搭建centos)

Docker安装(CentOS7)1.卸载旧版Docker#检查已安装版本yumlistinstalled|grepdocker#卸载旧版本yumremove-ydocker.x...

基础篇:数据库 SQL 入门教程(sql数据库入门书籍推荐)

SQL介绍什么是SQLSQL指结构化查询语言,是用于访问和处理数据库的标准的计算机语言。它使我们有能力访问数据库,可与多种数据库程序协同工作,如MSAccess、DB2、Informix、M...

Java21杀手级新特性!3行代码性能翻倍

导语某券商系统用这招,交易延迟从12ms降到0.8ms!本文揭秘Oracle官方未公开的Record模式匹配+虚拟线程深度优化+向量API神操作,代码量直降70%!一、Record模式匹配(代码量↓8...

一文读懂JDK21的虚拟线程(java虚拟线程)

概述JDK21已于2023年9月19日发布,作为Oracle标准Java实现的一个LTS版本发布,发布了15想新特性,其中虚拟线程呼声较高。虚拟线程是JDK21中引入的一项重要特性,它是一种轻量级的...

效率!MacOS下超级好用的Linux虚拟工具:Lima

对于MacOS用户来说,搭建Linux虚拟环境一直是件让人头疼的事。无论是VirtualBox还是商业的VMware,都显得过于笨重且配置复杂。今天,我们要介绍一个轻巧方便的纯命令行Linux虚拟工具...

所谓SaaS(所谓三维目标一般都应包括)

2010年前后,一个科技媒体的主编写一些关于云计算的概念性问题,就可以作为头版头条了。那时候的云计算,更多的还停留在一些概念性的问题上。而基于云计算而生的SaaS更是“养在深闺人未识”,一度成为被IT...

ORA-00600 「25027」 「x」报错(报错0xc0000001)

问题现象:在用到LOB大对象的业务中,进行数据的插入,失败了,在报警文件中报错:ORA-00600:内部错误代码,参数:[25027],[10],[0],[],[],[],[],[...

安卓7源码编译(安卓源码编译环境lunch失败,uname命令找不到)

前面已经下载好源码了,接下来是下载手机对应的二进制驱动执行编译源码命令下载厂商驱动https://developers.google.com/android/drivers?hl=zh-cn搜索NGI...

编译安卓源码(编译安卓源码 电脑配置)

前面已经下载好源码了,接下来是下载手机对应的二进制驱动执行编译源码命令下载厂商驱动https://developers.google.com/android/drivers?hl=zh-cn搜索NGI...

360 Vulcan Team首战告捷 以17.5万美金强势领跑2019“天府杯“

2019年11月16日,由360集团、百度、腾讯、阿里巴巴、清华大学与中科院等多家企业和研究机构在成都联合主办了2019“天府杯”国际网络安全大赛暨2019天府国际网络安全高峰论坛。而开幕当日最激荡人...

Syslog 日志分析与异常检测技巧(syslog发送日志配置)

系统日志包含有助于分析网络设备整体运行状况的重要信息。然而,理解并从中提取有效数据往往颇具挑战。本文将详解从基础命令行工具到专业日志管理软件的全流程分析技巧,助你高效挖掘Syslog日志价值。Gr...

从Oracle演进看数据库技术的发展(从oracle演进看数据库技术的发展的过程)

数据库技术发展本质上是应用需求驱动与基础架构演进的双向奔赴,如何分析其技术发展的脉络和方向?考虑到oracle数据库仍然是这个领域的王者,以其为例,管中窥豹,对其从Oracle8i到23ai版本的核...

取消回复欢迎 发表评论: