您当前的位置:首页 > 电脑百科 > 数据库 > 百科

Mybatis 中xml和注解映射,分分钟搞定

时间:2020-12-11 15:23:26  来源:  作者:

MyBatis 提供了XML配置和注解配置两种方式。今天就来搞搞这两种方式是如何实现的。

MyBatis 的真正强大在于它的语句映射,这是它的魔力所在。由于它的异常强大,映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。MyBatis 致力于减少使用成本,让用户能更专注于 SQL 代码。

来自官网。

Mybatis映射九个顶级元素:

Mybatis 中xml和注解映射,分分钟搞定

 

  • mApper:映射文件的根节点,只有一个属性namespace(命名空间),作用如下:
  • 用于区分不同的mapper,全局唯一。
  • 绑定DAO接口,即面向接口编程,当绑定一个接口,就不用写此接口的实现类,会通过接口的完全限定名找到对应的mapper配置来执行SQL语句,所以,namespace的命名必须要写接口的完全限定名。
  • cache:配置给定命名空间的缓存。
  • cache-ref:从其他命名空间引用缓存配置。
  • resultMap:用来描述数据库结果集和对象的对应关系。
  • sql:可以重用的SQL块,也可以被其他语句引用。通常是存放一些公用性的SQL。
  • insert:映射插入语句。
  • update:更新映射语句。
  • delete:删除映射语句。
  • select:映射查询语句。

 

Mybatis 中xml和注解映射,分分钟搞定

 

xml方式

九个顶级映射元素对应标签:

<mapper namespace="com.tian.mybatis.mapper.UserMapper">
    <resultMap id="" type=""></resultMap>
    <sql id=""></sql>
    <cache blocking="" ></cache>
    <cache-ref namespace=""></cache-ref>
    <select id="selectUserById"></select>
    <insert id="insert" ></insert>
    <update id=""></update>
    <delete id=""></delete>
</mapper>

select详解

 

Mybatis 中xml和注解映射,分分钟搞定

 

可以看得出,后面可选项还是蛮多的。下面是官网对每项的解释。

Mybatis 中xml和注解映射,分分钟搞定

 

select使用案例

<?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.tian.mybatis.mapper.UserMapper">
    <select id="selectUserById"  resultType="com.tian.mybatis.entity.User" parameterType="int" >
        select * from m_user where id = #{id}
    </select>
</mapper>
  • id必须在这个Mapper中是唯一的,可以被用来引用这条语句 ,这个id必须与之对应的是XxxMapper.JAVA中的方法,必须是一一对应。
  • 返回类型:User类型,resultType:查询语句返回结果类型的完全限定名或别名。别名使用方式和parameterType是一样的。
  • 参数:整形,表示查询语句传入参数的类型和完全限定名或别名。支持基础数据类型和复杂数据类型。

#{参数名}:告诉MyBatis生成的PreparedStatement参数,相对于JDBC中,该参数被标识为‘?’。

别名与参数映射类型如下:

Mybatis 中xml和注解映射,分分钟搞定

 

返回类型中别名的使用,注意:

如果是我们的entity类,那么resultType是无法使用别名的,只能使用resultMap才可以使用别名。

<?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.tian.mybatis.mapper.UserMapper">
    <resultMap id="User" type="com.tian.mybatis.entity.User"/>
    <select id="selectUserById"  resultMap="User" parameterType="int" >
        select * from m_user where id = #{id}
    </select>
</mapper>

但是如果使用的上面映射表里,也可以直接使用别名。

数据库里有两条数据:

Mybatis 中xml和注解映射,分分钟搞定

 

UserMapper.xml

<?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.tian.mybatis.mapper.UserMapper">
    <select id="countUser" resultType="int">
        select count(1) from m_user
    </select>
</mapper>

UserMapper.java

import com.tian.mybatis.entity.User;
public interface UserMapper {
    int countUser();
}

测试类:

public class MybatisApplication {
    public static final String URL = "jdbc:MySQL://localhost.com:3306/mblog?useUnicode=true";
    public static final String USER = "root";
    public static final String PASSword = "123456";
    public static void main(String[] args) {
        String resource = "mybatis-config.xml";
        InputStream inputStream = null;
        SqlSession sqlSession = null;
        try {
            inputStream = Resources.getResourceAsStream(resource);
            //工厂模式
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            //获取sql操作会话
            sqlSession = sqlSessionFactory.openSession();
            //构造对象(这里比较特殊,这里构造对象的方式后面会专门分享)
            UserMapper userMapper =  sqlSession.getMapper(UserMapper.class);
            //查询统计
            System.out.println(userMapper.countUser());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            sqlSession.close();
        }
    }
}

输出:2

当数据库表中的字段名和我们entity中的字段名不一致,怎么处理?

在实际开发中,这种常见是在所难免。我们可以使用下面的这种方式解决。

实体类User

public class User {
    private Integer id;
    private String userName;
    private Integer age; 
    //set get toString方法这里就不贴了
}

UserMapper.xml文件内容:

<?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.tian.mybatis.mapper.UserMapper">
    <resultMap id="User" type="com.tian.mybatis.entity.User">
        <id column="id" property="id"/>
        <result column="name" property="userName"/>
    </resultMap>
    <select id="selectUserById"  resultMap="User" parameterType="int" >
        select * from m_user where id = #{id}
    </select>
</mapper>

 

Mybatis 中xml和注解映射,分分钟搞定

 

  • type:对应的是我们的实体类,全路径名。
  • id:可以理解为别名。

 

Mybatis 中xml和注解映射,分分钟搞定

 

  • id:唯一标识,此id值用于select元素resultMap属性的引用。
  • column:对应我们数据库表中的字段名称。
  • property:对应我们的实体类的属性,比如:User中的属性userName,要和数据库表m_user中的name对应。
  • result:标识一些简单属性,其中column属性代表数据库的字段名,property代表查询出来的字段名映射到实体类的某个属性。

继续使用我们前面的测试类进行测试:

UserMapper userMapper =  sqlSession.getMapper(UserMapper.class);
System.out.println(userMapper.selectUserById(1));

输出:User{id=1, userName='tian', age=22}

注意:实体类的get set 和toString()方法这里给省略, 希望大家在使用的使用,使用快捷键很简单的就搞定了。

上面提到过resultType和resultMap,那么他们两到底有什么区别呢?

resultType和resultMap 有什么区别?

  • resultType:直接表示返回类型, 包括基本数据类型和复杂数据类型。
  • resultMap:外部resultMap定义的引用,通过对应的外部resultMap的id,表示结果映射到哪个resultMap上,一般用于字段名和属性名不一致的情况,或者需要做复杂的联合查询以便自由控制映射结果。

两者的关联

当进行查询时,查询出来的每个字段都会放在一个Map里,当查询元素返回属性是resultType的时候,会将键值对取出赋所指定的属性。其实MyBatis的每个查询映射的返回类型都是resultMap,只是当我们使用resultType的时候,会自动把对应的值赋给所指定的对象属性,当使用resultMap时候,因为map不是很好的表示领域,我们就进一步的转化为对应的实体对象。resultMap主要作用于复杂的联合查询上。

resultMap的自动映射级别:默认级别为PARTIAL,也可以在settings更改值。

注意:resultType和resultMap本质是一样的,都是Map数据结构,但是二者不能同时存在。

增删改案例

insert

Mybatis 中xml和注解映射,分分钟搞定

 

从这里可以知道,关于增加insert是没有返回值类型可以让我们指定的。默认返回int类型。

<insert id="insert" parameterType="com.tian.mybatis.entity.User">
        INSERT INTO m_user(`name`,age) VALUES ( #{userName},#{age})
</insert>

对应Mapper中的方法

int insert(User user);

另外的update和delete类似,这里就没有必要逐一演示了。

注解方式

九个顶级映射元素对应注解:

Mybatis 中xml和注解映射,分分钟搞定

 

其他部分注解是配合九个注解进行使用的。

select注解

把本地的UserMapper.xml删掉,然后改一下mybatis-config.xml,把其中的UserMapper.xml给注释掉。添加

<mapper class="com.tian.mybatis.mapper.UserMapper"/>

UserMapper.java添加注解

public interface UserMapper {
    @Select("select * from m_user where id = #{id}")
    User selectUserById(Integer id);
}

再次测试

User user = sqlSession.selectOne("com.tian.mybatis.mapper.UserMapper.selectUserById", 1);
System.out.println(user);

输出:

User{id=1, userName='null', age=22}

从输出内容看到,userName为null,这也是因为和数据库表格中的字段name不一致导致的,那么如何处理呢?

这么搞,再添加一个注解:

public interface UserMapper {
   @Select("select * from m_user where id = #{id}")
   @Results( @Result(column = "name",property = "userName"))
   User selectUserById(Integer id);
}

输出:

User{id=1, userName='tian', age=22}

这样也就是在使用注解的时候,处理实体属性名和数据库表字段名不一样的问题的办法。

insert、update、delete同样也可以使用注解来搞定了。

@Insert、@Update、@Delete配上相应的SQL语句。

注解和xml是否可以共存?

    <update id="updateAuthorIfNecessary">
        update m_user
        <trim prefix="SET" suffixOverrides=",">
            <if test="userName != null and userName != ''">
                `name` = #{userName},
            </if>
            <if test="gender != null and gender != 0">
                gender = #{gender},
            </if>
            <if test="age != null and age != 0">
                age = #{age},
            </if>
        </trim>
        where id=#{id}
    </update>

同时在UserMapper.java中的方法上添加注解

@Update("update m_user set  `name` = #{userName},gender = #{gender},age = #{age} where id=#{id}")
int updateAuthorIfNecessary(User user);

再次中子星的时候回报异常的:

nested exception is java.lang.IllegalArgumentException:
Mapped Statements collection already contains value for com.tian.mybatis.mapper.UserMapper.updateAuthorIfNecessary. 
please check file [D:workspacemy_codemybatistargetclassesmapperUserMapper.xml] and com/tian/mybatis/mapper/UserMapper.java (best guess)

大致意思就是说,已经存在了,即就是不能同时使用xml和注解。二者选其一。

xml可以和注解结合使用,但是得保证同一个方法不能同时存在xml和注解。

建议

简单的sql处理可以使用注解,复杂的sql使用xml。但是实际工作还得看你待的项目中有没有对这个进行规范化。

在项目中无非就三种:

1.全部必须使用xml方式。

2.全部必须使用注解方式。

3.可以同时使用xml和注解。

高级映射

association

映射到JavaBean的某个复杂的”数据类型”属性,仅处理一对一的关联关系。

<resultMap type="com.tian.mybatis.entity.User" id="userMapRole">
        <id column="id" property="id" />
        <result column="name" property="userName" />
        <result column="age" property="age" />
        <association property="role" javaType="UserRole">
            <id column="id" property="id" />
            <result column="roleName" property="roleName" />
        </association>
</resultMap>

association的属性节点:

  • property:映射数据库列的实体对象属性名。
  • javaType:完整的java类名和限定名。propert所映射的属性的类型。

子元素

  • id:一般为映射主键,可以提高性能。
  • result:
  • column:映射的数据库的字段名。
  • property:映射的数据列对应的实体对象属性。

collection

映射到JavaBean的某个复杂的”数据类型”属性,这个属性是一个集合列表,处理一对多的关联关系。

<resultMap type="com.tian.mybatis.entity.User" id="userMapAddress">
        <id column="id" property="id"/>
        <result column="name" property="userName"/>
        <collection property="lists" ofType="UserAddress">       
            <id column = "id" property = "id">
            <result column="addressDesc" property="addressDesc"/>
        </collection>
    </resultMap>

ofType:完整的Java类名和限定名。propert所映射的属性的类型。

其余和association基本一致。

association和collection都具备延迟加载功能。

延迟加载:先从单表查询,需要时再查关联表,大大的提高了数据库性能,因为相对来说单表查询比多表查询要快。

xml和注解的关系

上面我们已经讲了两种方式的实现,下面来对比一下,两种方式的关系:

xml方式

必须有个一个XxxMapper.xml与之对应,方法名对应xml中的id,方法入参和方法出参都必须对应起来,很容易出问题。我们在开发的时候有的是可以使用代码生成器生成,但是有的是必须自己手写,有的公司也是要求必须手写,所以这里需要注意。

注解方式

不需要XxxMapper.xml文件,只需要在对应XxxMapper.java中的方法上加上注解就搞定了,但是这里是有坑的。毕竟把sql放到了我们的Java代码里了。

优缺点

xml方式: 增加了xml文件,修改麻烦,条件不确定(ifelse判断),容易出错,特殊转义字符比如大于小于 。

注解方式:复杂sql不好用,搜集sql不方便,管理不方便,修改需重新编译

总结

本文讲述了Mybatis的两种映射方式,以及一些注意点,一些关系和区别。

实体属性名和数据库表字段名不一样的情况下,xml和注解分别是如何处理的。resultType和resultMap的区别。



Tags:Mybatis   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
本篇文章主要介绍了使用MyBatis框架完成数据库的增、删、改、查操作。准备工作运行schema.sql和data.sql脚本文件中的 SQL 语句创建t_user表并添加部分测试数据。schema.sql...【详细内容】
2022-07-15  Tags: Mybatis  点击:(0)  评论:(0)  加入收藏
简介MetaObject 是 MyBatis 中的反射工具类,用于获取和设置对象的属性值。示例List<Order> orders = new ArrayList<>(2);orders.add(new Order("1", "001", "美的电压力锅")...【详细内容】
2022-07-06  Tags: Mybatis  点击:(18)  评论:(0)  加入收藏
简介SqlRunner,一个非常实用的、用于操作数据库的工具类。该类对JDBC进行了很好的封装,结合SQL工具类,能够很方便地通过Java代码执行SQL语句并检索SQL执行结果。SqlRunner提供...【详细内容】
2022-07-05  Tags: Mybatis  点击:(19)  评论:(0)  加入收藏
1. If 语句需求:根据作者名字和博客名字来查询博客!如果作者名字为空,那么只根据博客名字查询,反之,则根据作者名字来查询<!--需求1:根据作者名字和博客名字来查询博客!如果作者名...【详细内容】
2022-06-30  Tags: Mybatis  点击:(25)  评论:(0)  加入收藏
在进行持久层数据维护(新增或修改)的时候,我们通常需要记录一些非业务字段,比如:create_time、update_time、update_by、create_by等用来维护数据记录的创建时间、修改时间、修改...【详细内容】
2022-06-20  Tags: Mybatis  点击:(23)  评论:(0)  加入收藏
Mybatis 是 Java 中一个非常好用的数据库框架,这儿记录一下在使用过程中遇到的坑。官方中文文档地址:http://www.mybatis.org/mybatis-3/zh/getting-started.html1、在Mybatis...【详细内容】
2022-06-20  Tags: Mybatis  点击:(34)  评论:(0)  加入收藏
今天介绍一个 MyBatis - Plus 官方发布的神器:mybatis-mate 为 mp 企业级模块,支持分库分表,数据审计、数据敏感词过滤(AC算法),字段加密,字典回写(数据绑定),数据权限,表结构自动生成...【详细内容】
2022-06-17  Tags: Mybatis  点击:(43)  评论:(0)  加入收藏
1. Mybatis 存在的痛点我们知道 MyBatis 是一个基于 java 的持久层框架,它内部封装了 jdbc,极大提高了我们的开发效率。但是使用 Mybatis 开发也有很多痛点: 每个 Dao 接口都需...【详细内容】
2022-06-14  Tags: Mybatis  点击:(37)  评论:(0)  加入收藏
MybatisPlus是国产的第三方插件, 它封装了许多常用的CURDapi,免去了我们写mapper.xml的重复劳动,这里介绍了基本的整合SpringBoot和基础用法。2|0引入依赖在项目中pom文件引入m...【详细内容】
2022-05-05  Tags: Mybatis  点击:(52)  评论:(0)  加入收藏
一、前言我们在日常开发中经常使用ORM框架,比如Mybatis、tk.Mybatis、Mybatis-Plus。不过最广泛的还是Mybatis-Plus,我们的一些表,都会有创建时间、更新时间、创建人、更新人。...【详细内容】
2022-04-24  Tags: Mybatis  点击:(172)  评论:(0)  加入收藏
▌简易百科推荐
俗话说,天下大势,合久必分、分久必合。数据库领域同样如此。过去五十余年,数据库经历OLTP和OLAP两种需求漫长的融合-分离-再融合的过程。究其原因,数据库的发展始终与用户场景需...【详细内容】
2022-07-14  大数据在线    Tags:HTAP数据库   点击:(4)  评论:(0)  加入收藏
导读:Apache HBase(Hadoop Database),是一个基于Google BigTable论文设计的高可靠性、高性能、可伸缩的分布式存储系统。全文将围绕以下几个方面展开: HBase是什么 HBase社区的发...【详细内容】
2022-07-08  DataFunTalk    Tags:Apache HBase   点击:(10)  评论:(0)  加入收藏
TimescaleDB 超表TimescaleDB 中使用称为 hypertables 的数据表来存储数据。hypertable(超表)是与数据交互的主要点,因为它提供了可以通过标准 SQL 查询的标准表抽象。 在 Time...【详细内容】
2022-07-07  IT职业教育    Tags:TimescaleDB   点击:(19)  评论:(0)  加入收藏
使用like、between、in进行模糊查询select * from Studentswhrere 姓名 like &#39;张%&#39;通配符:_ 一个字符,% 任意长度的字符串,[] 括号中所指定的范围内的一个字符,[^]不在...【详细内容】
2022-07-07  新米米    Tags:数据库   点击:(15)  评论:(0)  加入收藏
oracle经常需要查数据库表空间大小,使用率,加表空间等,这里总结我经常使用的语句。一、数据表空间相关:查询所有表空间的使用情况:SELECT d.tablespace_name "Name", d.status "S...【详细内容】
2022-07-07  运维Danrtsey    Tags:数据表   点击:(15)  评论:(0)  加入收藏
导读:本文将介绍Apache IoTDB,它是一个基于开放数据格式的数据库。今天的介绍会围绕下面四点展开: Apache IoTDB 简介 时序文件格式 TsFile 基于开放文件的数据库架构 开源社区...【详细内容】
2022-07-06  DataFunTalk    Tags:时序数据库   点击:(22)  评论:(0)  加入收藏
一、问题 在好大夫在线内部,S3系统负责各业务方操作日志的集中存储、查询和管理。目前,该系统日均查询量数千万次,插入量数十万次。随着日志量的不断累积,主表已经达到数十亿,单...【详细内容】
2022-07-05  dbaplus社群    Tags:MongoDB   点击:(16)  评论:(0)  加入收藏
文丨刘雨琦马云曾说,数据是当下“最贵”的资产,若阿里巴巴不搞云计算,可能就会死掉。而数据库作为整个数据行业的基础软件,正在迎来它的春天。国产数据库的接连上市,为信创风口...【详细内容】
2022-07-05  光锥智能    Tags:数据库   点击:(20)  评论:(0)  加入收藏
导读:埋点数据是数据分析、推荐、运营的基础,低延时、稳定、高效的埋点数据流对提高用户体验有着非常重要的作用。而随着流量的增大,埋点的增多,在大流量场景下,埋点数据流的建设...【详细内容】
2022-07-05  DataFunTalk    Tags:数据   点击:(22)  评论:(0)  加入收藏
作为轻量级的本地存储方式,对于构建不依赖服务器的小型项目,用LowDB存储和管理数据是十分理想的选择。在Nodejs, Electron and browser等一些小型项目中经常能看到LowDB的身影...【详细内容】
2022-07-04    效能哥  Tags:数据库   点击:(30)  评论:(0)  加入收藏
站内最新
站内热门
站内头条