Mybatis2

news2024/11/23 12:44:07

 

Mybatis2

本章目标:

  1. myBatis类型别名处理

  2. myBatis参数处理

  3. myBatis结果集类型

  4. myBatis结果集列名和属性名称对应方式处理

  5. 附录

本章内容

一、类型别名(typeAliases)处理

类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写。例如,在配置文件中加入以下配置:

自己配置类型别名

配置方式一:

<typeAliases>
    <typeAlias type="com.entity.Dept" alias="dept"/>
</typeAliases>

配置方式二:直接配置包名:底层会为包中的每一个类自动起别名(类的短名(movie|Movie))

<typeAliases>    
    <package name="com.entity"/>
</typeAliases>

已有的类型别名

别名 类型

_bytebyte
_longlong
_shortshort
_intint
_integerint
_doubledouble
_floatfloat
_booleanboolean
stringString
byteByte
longLong
shortShort
intInteger
integerInteger
doubleDouble
floatFloat
booleanBoolean
dateDate
decimalBigDecimal
bigdecimalBigDecimal
objectObject
mapMap
hashmapHashMap
listList
arraylistArrayList
collectionCollection
iteratorIterator
二、MyBatis参数处理:
  1. 单个参数,参数非实体类类型(简单数据类型—八种基本数据类型及对应的封装类、Date,String)

    接口方法

    public void deleteStudentById(Integer studentId);

    映射文件

    <delete id="deleteStudentById" parameterType="integer">
        delete from student where student_id=#{student_id}
    </delete>
    <delete id="deleteStudentById" parameterType="int">
        delete from student where student_id=#{student_id}
    </delete>

    单个参数:parameterType可以不写,管理比较松散,如果写了,只要类型匹配就可以了(映射期接口中方法的参数类型和映射文件中的parameterType的属性值应该匹配,parameterType和参数类型一致或者能够方法参数类型的父类类型),名称无所谓,如果参数为int,配置为short,则会出现异常,参数名称没有要求

    ### Error updating database. Cause: org.apache.ibatis.type.TypeException: Could not set parameters for mapping: ParameterMapping{property='student_id', mode=IN, javaType=class java.lang.Short, jdbcType=null, numericScale=null, resultMapId='null', jdbcTypeName='null', expression='null'}. Cause: org.apache.ibatis.type.TypeException: Error setting non null for parameter #1 with JdbcType null . Try setting a different JdbcType for this parameter or a different configuration property. Cause: java.lang.ClassCastException:

  2. 多个参数,且非实体类类型

    接口中的方法

    public void saveStudent1(String studentName,String studentSex);

    映射文件第一种方式

    <insert id="saveStudent1" >
        insert into student(student_id,student_name,student_sex)values(20,#{arg0},#{arg1})
    </insert>

    映射文件第二种方式

    <insert id="saveStudent1" >    
        insert into student(student_id,student_name,student_sex)    values(21,#{param1},#{param2})    
    </insert>

    以上两种方式的问题:参数名称补明确,不能望文生义,于是有第三种方式,借助于Param注解

    映射文件第三种方式(重点掌握)

    接口方法:

    public void saveStudent1(@Param("sname")String studentName,@Param("ssex")String studentSex);

    映射文件:

    <insert id="saveStudent1" >             
        insert into student(student_id,student_name,student_sex)values(22,#{sname},#{ssex})    
    </insert>
  3. 实体类类型参数

    接口方法

    public void saveStudent(Student s);

    映射文件

    <insert id="saveStudent" parameterType="Student">             
    insert into student(student_id,student_name,student_sex,student_grade,student_profession,student_age)           values(#{student_id},#{student_name},#{student_sex},#{student_grade},#{student_profession},#{student_age})</insert>

    注意:#{实体类对象属性名称} 参数名 称要和pojo属性名称一致,原理:先找getter,再根据属性进行匹配

  4. 带多个参数并且有的为实体类类型

    映射器接口:

    public List<Student> selectStudent2(@Param("s")Student s,@Param("sname")String sname);

    映射文件 :

    <select id="selectStudent2" resultType="student">    
        select * from student where student_id=#{s.student_id} and student_name=#{sname}
    </select>
  5. map参数

    接口

    public List selectEmpByEnameAndEmpno1(Map params);

    映射文件:依靠map集合的键进行值的引用

    <select id="selectEmpByEnameAndEmpno1" parameterType="map" resultType="emp"> 
    	SELECT * FROM emp WHERE ename LIKE CONCAT('%',#{key1},'%') AND empno=#{key2}
    </select>

    测试

    public void test5(){    
    	SqlSession sqlSession= MyBatisUtil.crateSqlSession();    
        EmpMapper empMapper=sqlSession.getMapper(EmpMapper.class);     
        Map<String,Object> param=new HashMap<>();    
        param.put("key1","A");    param.put("key2",(short)7900);    
        List<Emp> emps=empMapper.selectEmpByEnameAndEmpno1(param);    
        logger.info(emps);    
        MyBatisUtil.closeSqlSession(sqlSession);
    }
  6. 精确指定参数类型,解决类型的对应问题

    #{property,javaType=int,jdbcType=NUMERIC}

    不指定会按照默认的处理方式进行处理,但是一些特殊的数据类型如Date类型可能不符合我们的要求,那就需要精确指定(uitl.Date能表示 年月日 年月日时分秒,如果不指定,默认会取年月日时分秒)

    #{property,javaType=int,jdbcType=NUMERIC}<insert id="saveMovie"  parameterType="Movie">    
    <!-- #{实体类对象的属性名称}:自动获取对应的属性值,默认调用#号后的属性对应的getter获取属性值,如果getter找不到,会直接找同名的属性 -->    
    insert into movies(movie_code,movie_name,movie_time,movie_date,movie_price,movie_com,movie_type)values(${movie_code},#{movie_name,javaType=string,jdbcType=VARCHAR},#{movie_time,javaType=int,jdbcType=INTEGER},#{movie_date,javaType=date,jdbcType=DATE},#{movie_price,javaType=float,jdbcType=FLOAT},#{movie_com,javaType=int,jdbcType=INTEGER},#{movie_type,javaType=int,jdbcType=INTEGER})  
    </insert>
  7. $和#的区别(面试爱问)

    $:引用的值会直接替换sql语句中的部分,编译的时候值已经替换了,常见于设置表名列名等信息

    #:会在sql中先处理为?,进行预编译,编译之后,然后再进行值的替换

  8. 总结

    如果参数多于4个以上,建议不要单独写,这种情况在特殊业务情况下必须使用实体对象和map比较通用

三、myBatis结果集结果集返回类型的处理
  1. 返回单个对象(单个实体类对象)

    接口方法

    public Student getStudentById(Integer studentId);

    映射文件

    <select id="getStudentById" parameterType="integer" resultType="Student">          
    	select * from student where student_id=#{ids}     
    </select>
  2. 返回集合(封装的依然为实体类对象)

    接口方法

    public List<Student>getAll();

    映射文件集合中封装的实体类类型

    <select id="getAll" resultType="Student"> select * from student </select>

  3. 返回Map,返回的是一行记录,将一行记录封装到map中 ,键为结果集的列名,值就是结果集对应列的值

    实例1:(建议用实体类对象返回,了解)

    接口方法

    public Map<String, Object> getStudentReturnMap(Integer studentId);

    映射文件

    <select id="getStudentReturnMap" resultType="map">    
    select * from student where student_id=#{ids}
    </select>

    测试方法:

    session=sqlSessionFactory.openSession();
    StudentMapper mapper=session.getMapper(StudentMapper.class);
    Map<String,Object> map=mapper.getStudentReturnMap(id);
    System.out.println(map);
    session.commit();
    session.close();

    实例二:返回多个聚合函数的结果(多见)

    接口方法

    public Map<String, Object> getCountAndAge();

    映射文件

    map中封装的数据:

    结果集的列名-(键)———对应列的值(值)

    <select id="getCountAndAge" resultType="map">
    select count(student_id) as studentCount,max(student_age) as studentAge from student
    </select>

    测试

    SqlSession session=sqlSessionFactory.openSession();
    StudentMapper mapper=session.getMapper(StudentMapper.class);
    Map<String,Object> map=mapper.getCountAndAge();
    System.out.println(map);
    session.commit();
    session.close();
  4. 返回多条记录List

    返回分组聚合的结果(多见,重点掌握)

    image-20220602153406395

    接口方法

    接口方法:    /*接收分组统计之后的结果     *      * 
    {studentCount=10, studentAge=25}
    {studentCount=25, student_grade=1, studentAge=26}
    {studentCount=2, student_grade=2, studentAge=25}
    {studentCount=2, student_grade=3, studentAge=25}
    {studentCount=1, student_grade=4, studentAge=27} 
    会将每一行数据先封装为一个map,以结果集的列名作为键,对应列的值作为值, 然后将map封装到List中     
    *      
    * */
    public List<Map<String, Object>> getCountAndAgeByGrade();

    映射文件

    <select id="getCountAndAgeByGrade" resultType="map">    
    select student_grade,count(student_id) as studentCount,max(student_age) as studentAge from student group by student_grade
    </select>

    测试

    SqlSession sqlSession=DBTools.getSqlSession();
    //会根据命名空间+id去找对应的标记,执行标记中sql语句,根据配置的结果集类型进行封装
    //根据sqlSession。getMapper传入的接口类型,得到一个接口对应的实现类型对象
    //调用接口中的方法(会自动执行映射文件中对应的sql)
    StudentMapper mapper=sqlSession.getMapper(StudentMapper.class);
    //获得一条记录,返回值为map
    List<Map<String,Object>> l=mapper.getCountAndAgeByGrade();
    for(Map<String, Object> map:l){    
    	System.out.println(map);
    }
四、结果集的列名和实体类属性名称对应方式的处理

默认按照属性名称和结果集列名一致的原则进行封装,如果不一致,会有以下处理方式

  1. 如上虽然数据库已经查到了数据,但是由于数据库字段的名称和实体对象的属性名称不一致,这样resultType属性就不能实现自动的设置,遇到这样问题,有如下三种解决方案

  • 使用AS关键字来解决

    <select id="findAllPerson"resultType="person">     
    SELECT person_id AS personId,person_name AS personName,person_age personAge FROM person
    </select>
  • 如果你的项目中采用驼峰命名法,那么可以在mybatis-cofig.xml文件中进行设置person_id==>personId(要求:项目中的pojo需要符合驼峰命名法的规则)

    结果的列名为下划线风格,实体类的属性名称为驼峰风格,才有必要这样使用

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

    注意:如上设置一定实体类的属性要符合驼峰命名法才行,否则不能起到效果

  • 采用resultMap方式来解决(推荐使用)

    image-20220602164317765

    可以解决如下问题:

    1)列名和属性名称对应的问题

    2)数据类型对应的问题(如何对应,查看笔记第四部分附录)

    3)关联映射

    配置resultMap(自定义结果集的映射方式)

    <mapper namespace="com.dao.GradeMapper">
        <resultMap type="grade" id="gradeResult">        
            <id property="gradeId" column="grade_id" javaType="integer" jdbcType="INTEGER"/>    
            <result property="gradeName" column="grade_name" javaType="string" jdbcType="VARCHAR"/></resultMap>
        <select id="getAll"  resultMap="gradeResult">     
            select * from grade     
        </select>    
    </mapper>

    这两者之间的唯一不同是,id 元素对应的属性会被标记为对象的标识符,在比较对象实例时使用。 这样可以提高整体的性能,尤其是进行缓存和嵌套结果映射(也就是连接映射)的时候。

    注意:select标记的resultMap属性和resultType属性的区别

    resultType:属性值是一个具体的类型,用的是列名和属性名称一致原则自动封装

    resultMap:属性值是映射文件中resultMap标记的id属性的属性值,想采用自定义的映射规则去进行封装

五、附录

数据库数据类型和JAVA类型的对应关系

两个元素都有一些属性:

属性描述
property映射到列结果的字段或属性。如果 JavaBean 有这个名字的属性(property),会先使用该属性。否则 MyBatis 将会寻找给定名称的字段(field)。 无论是哪一种情形,你都可以使用常见的点式分隔形式进行复杂属性导航。 比如,你可以这样映射一些简单的东西:“username”,或者映射到一些复杂的东西上:“address.street.number”。
column数据库中的列名,或者是列的别名。一般情况下,这和传递给 resultSet.getString(columnName) 方法的参数一样。
javaType一个 Java 类的全限定名,或一个类型别名(关于内置的类型别名,可以参考上面的表格)。 如果你映射到一个 JavaBean,MyBatis 通常可以推断类型。然而,如果你映射到的是 HashMap,那么你应该明确地指定 javaType 来保证行为与期望的相一致。
jdbcTypeJDBC 类型,所支持的 JDBC 类型参见这个表格之后的“支持的 JDBC 类型”。 只需要在可能执行插入、更新和删除的且允许空值的列上指定 JDBC 类型。这是 JDBC 的要求而非 MyBatis 的要求。如果你直接面向 JDBC 编程,你需要对可以为空值的列指定这个类型。

支持的 JDBC 类型

为了以后可能的使用场景,MyBatis 通过内置的 jdbcType 枚举类型支持下面的 JDBC 类型。

BITFLOATCHARTIMESTAMPOTHERUNDEFINED
TINYINTREALVARCHARBINARYBLOBNVARCHAR
SMALLINTDOUBLELONGVARCHARVARBINARYCLOBNCHAR
INTEGERNUMERICDATELONGVARBINARYBOOLEANNCLOB
BIGINTDECIMALTIMENULLCURSORARRAY

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1472666.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用EFCore连接SQLite

简介 在使用EFCore连接SQLite之前我们先来了解一下SQLite SQLite是一个轻量级、自包含、无服务器、零配置的事务性SQL数据库引擎&#xff0c;它支持SQL92标准的大多数查询语言并兼容ACID事务。具体如下&#xff1a; 轻量级&#xff1a;SQLite非常轻巧&#xff0c;它的库体积…

[算法沉淀记录] 排序算法 —— 堆排序

排序算法 —— 堆排序 算法基础介绍 堆排序&#xff08;Heap Sort&#xff09;是一种基于比较的排序算法&#xff0c;它利用堆这种数据结构来实现排序。堆是一种特殊的完全二叉树&#xff0c;其中每个节点的值都必须大于或等于&#xff08;最大堆&#xff09;或小于或等于&am…

Huggingface学习笔记

课程地址&#xff1a;【HuggingFace简明教程,BERT中文模型实战示例.NLP预训练模型,Transformers类库,datasets类库快速入门.】 什么是huggingface&#xff1f; huggingface是一个开源社区&#xff0c;提供了先进的NLP模型、数据集以及工具。 主要模型&#xff1a; 安装环境&…

Rust升级慢,使用国内镜像进行加速

背景 rustup 是 Rust 官方的跨平台 Rust 安装工具&#xff0c;国内用户使用rustup update的时候&#xff0c;网速非常慢&#xff0c;可以使用国内的阿里云镜像源来进行加速 0x01 配置方法 1. Linux与Mac OS用户配置环境变量 修改~/.bash_profile文件添加如下内容&#xff1…

Docker基础篇(六) dockerfile体系结构语法

FROM&#xff1a;基础镜像&#xff0c;当前新镜像是基于哪个镜像的 MAINTAINER &#xff1a;镜像维护者的姓名和邮箱地址 RUN&#xff1a;容器构建时需要运行的命令 EXPOSE &#xff1a;当前容器对外暴露出的端口号 WORKDIR&#xff1a;指定在创建容器后&#xff0c;终端默认登…

lv21 QT入门与基础控件 1

1 QT简介 QT是挪威Trolltech开发的多平台C图形用户界面应用程序框架 典型应用 2 工程搭建 2.1 新建ui工程 不要写中文路径 2.1 不勾选UI&#xff08;主讲&#xff09; 3 QT信号与槽机制 语法&#xff1a;Connect&#xff08;A, SIGNLA(aaa()), B, SLOT(bbb())&#xff09;…

算法--贪心

这里写目录标题 区间问题区间选点引入算法思想例题代码 最大不相交区间的数量算法思想例题代码 区间分组算法思想例题代码 一级目录二级目录二级目录二级目录 区间问题 区间选点 引入 区间问题会给定几个区间&#xff0c;之后要求我们在数轴上选取尽量少的点&#xff0c;使得…

电脑休眠之后唤不醒

现象&#xff1a;午休时间电脑休眠了&#xff0c;醒来之后发现在密码输入界面&#xff0c;但鼠标键盘没反应。按重启键或电源机重新开机&#xff0c;结果开不了机。 原因&#xff1a;1、内存条脏了&#xff0c;导致内存条读取失败 2、休眠的时候硬盘休眠了&#xff0c;导致按…

欢迎免费申报讯方技术HarmonyOS人才训练营!

在今年1月备受瞩目的鸿蒙生态千帆启航仪式上&#xff0c;华为宣布&#xff1a;HarmonyOS NEXT星河预览版正式面向开发者开放申请&#xff0c;意味着鸿蒙将建立更广泛的生态系统&#xff0c;迎来更多的应用和软硬件产品&#xff0c;加速自我技术迭代&#xff0c;同时推动华为全场…

变革中的容器技术

容器化技术的优点 容器化是一种将应用程序和其所需的依赖项&#xff0c;封装在一个可在任何基础架构上一致运行的轻量级可执行文件&#xff08;即容器&#xff09;的技术。容器化技术可以大大简化应用程序的部署、管理和维护&#xff0c;提高运维效率和可靠性。 容器化技术有…

LeetCode_Java_动态规划(2)(题目+思路+代码)

131.分割回文串 给你一个字符串 s&#xff0c;请你将 s 分割成一些子串&#xff0c;使每个子串都是 回文串 。返回 s 所有可能的分割方案。 回文串 是正着读和反着读都一样的字符串。 示例 1&#xff1a; 输入&#xff1a;s "aab" 输出&#xff1a;[["a&qu…

工具篇-- 定时任务xxl-job的集群部署

文章目录 前言一、xxl-job-admin 集群部署&#xff1a;1.1 部署步骤&#xff1a;1.2 部署求和建议&#xff1a;1.3 集群部署模拟&#xff08;单机&#xff09;&#xff1a; 二、xxl-job 执行器 集群部署&#xff1a;2.1 集群部署要求&#xff1a;2.2 集群部署模拟&#xff1a; …

pthread_exit和pehread_join函数

pthread_exit&#xff1a; 在线程中禁止调用exit函数&#xff0c;否则会导致整个进程退出&#xff0c;取而代之的是调用pthread_exit函数&#xff0c;这个函数只会使一个线程退出&#xff0c;如果主线程使用pthread_exit函数也不会使整个进程退出&#xff0c;不会影响其他线程…

【基础知识】MPP架构和hadoop架构比对

架构比对 简单一句描述。 mpp架构&#xff0c;就是找一群和自己能力差不多的任一起做事&#xff0c;每个人做的事情是一致的。 hadoop架构&#xff0c;就是找一群能力差一些的人&#xff0c;但只需要他们每个人只做一部分工作。 举例说明 一个特色小饭店如何成为连锁餐饮巨…

【国密算法】深入理解国密算法:原理、实践及注意事项

目录 引言 1. 国密算法概述 2. 国密算法的实践应用 2.1 对称加密&#xff08;SM1算法&#xff09; 2.2 非对称加密&#xff08;SM2算法&#xff09; 2.3 哈希算法&#xff08;SM3算法&#xff09; 3. 国密算法的注意事项 结论 引言 国密算法&#xff0c;即中国密码算法…

AI数字人SadTalker实战

1.概述 AI数字人在营销和品牌推广中扮演着至关重要的角色&#xff0c;许多企业和个人正积极利用数字技术来打造属于自己的财富。有没有一种简单而免费的方式来创建自己的数字人呢&#xff1f;本篇博客笔者将为大家介绍如何搭建属于自己的AI数字人。 2.内容 2.1 什么是SadTalker…

内存卡无法读取?这里有救!

一、遭遇内存卡无法读取的困境 在日常生活和工作中&#xff0c;我们越来越依赖电子设备来存储和传输数据。然而&#xff0c;当遇到内存卡无法读取的问题时&#xff0c;很多人会感到困惑和焦虑。无论是重要的工作文件、珍贵的家庭照片&#xff0c;还是其他个人数据&#xff0c;…

基于springboot+vue的音乐网站(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

C++力扣题目 42--接雨水 84--柱状图中最大的矩形

42. 接雨水 力扣题目链接(opens new window) 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 示例 1&#xff1a; 输入&#xff1a;height [0,1,0,2,1,0,1,3,2,1,2,1]输出&#xff1a;6解释&#xff…

C++17之折叠表达式

相关文章系列 深入理解可变参数(va_list、std::initializer_list和可变参数模版) 目录 1.介绍 2.应用 2.1.使用折叠表达式 2.2.支持的运算符 2.3.使用折叠处理类型 3.总结 1.介绍 折叠表达式是C17新引进的语法特性。使用折叠表达式可以简化对C11中引入的参数包的处理&…