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

Mybatis的基础和高级查询应用实践

toqiye 2024-09-08 09:42 4 浏览 0 评论

前言

将分为3部分介绍:

  • 基本应用
  • 基于xml的复杂映射开发
  • Mybatis注解开发

[玫瑰][玫瑰]你的“关注”“收藏”是我最大的动力。非常感谢。[玫瑰][玫瑰]

#java##数据库##开发##后端#

基本应用

1.快速入门

快速入门查看官网 :http://www.mybatis.org/mybatis-3

开发步骤

1.添加Mybatis的坐标(添加pom.xml依赖)

<!--mybatis-->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.4.5</version>
</dependency>
<!--mysql驱动-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.6</version>
    <scope>runtime</scope>
</dependency>

2.创建数据库表 + 编写实体

表设计和实体根据自己业务实际编写即可

3.编写映射文件Mapper.xml与标签说明


<!--
    <?xml ...>    映射文件DTD约束头
    <mapper>    根标签
        namespae    命名空间,与语句ID标识id组成查询的标识
    <select>    查询操作
    <update>    更新操作
    <insert>    添加操作
    <delete>    删除操作
        id                语句ID标识,与命名空间一起组织成查询标识
        resultType        查询结果对应的实体类型
        parameterType    查询对象类型
-->
<?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="UserMapper">
    <select id="find" resultType="com.otoom.pojo.User" parameterType="com.otoom.pojo.User">
        select * from User WHERE username = #{username}
    </select>
</mapper>

4.编写核心文件SqlMapConfig.xml

<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN“ "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <properties resource="jdbc.properties"/>
       <!--环境,默认环境为:development-->
    <environments default="development">
        <!--环境配置-->
        <environment id="development">
            <!--当前事务交给JDBC处理-->
            <transactionManager type="JDBC"/>
            <!--使用mybatis提供的连接池-->
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                    <property name="url" value="${jdbc.url}"/>
                    <property name="username" value="${jdbc.username}"/>
                    <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    <!--引入配置文件-->
    <mappers>
        <!--使用指定文件路径
        <mapper resource="com/xxx/mapper/UserMapper.xml"/>
        -->

        <!--
            指定包名,会扫描这个文件夹下所有的xml
            这个xml的路径包名在resource中,需要和接口的包名一致
            如: resources目录下:com/xxx/mapper 存放xml文件
        -->
        <package name="com.xxx.mapper"/>
    </mappers>
</configuration>

5.使用

public static void main(String[] args){
    //获取配置信息
    InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml"); 
    //获取工厂类
    SqlSessionFactory sqlSessionFactory = 
        new SqlSessionFactoryBuilder().build(resourceAsStream); 
    //开启sql会话
    SqlSession sqlSession = sqlSessionFactory.openSession(); 
    //开始执行对应操作
    User query = new User();
    query.setUsername("Tom"); 
    int insert = sqlSession.insert("userMapper.find", query);
    //提交事务 
    //sqlSession.commit(); //CUD操作需要提交事务
    //关闭会话
    sqlSession.close();
}

sqlConfig.xml核心配置文件标签说明

<environments>: 数据库环境的配置,支持多种环境配置

<environment>: 环境变量

<transactionManager>: 事务管理器,有两种类型:

  1. JDBC:使用了JDBC的提交和回滚设置,依赖于从数据源得到的链接来管理事务作用域
  2. MANAGED:这个配置几乎什么都没有做,它从不提交和回滚一个链接,而是让容器去管理事务的整个生命周期。默认情况下它会关闭连接,然后有些容器不希望关闭,所以需要将 closeConnection 属性设置为false来阻止它的默认行为

<dataSource>: 数据源,有三种类型:

  1. UNPOOLED:非连接池类型。这个数据源实现的只是每次请求时打开和关闭连接
  2. POOLED:连接池类型。这种数据源实现利用"池"的概念将JDBC连接对象组织起来
  3. JNDI:这个数据源实现是为了能在如EJB或者应用服务器这类的容器中使用,容器可以集中或在外部配置数据源,然后放置一个JNDI上下文引用

<property>: 属性

<propertys>: 属性该标签可以加载额外配置的properties文件,如resource文件夹下的jdbc.properties。使用方式为:${jdbc.driver} 可以引用对应的值

<mappers>: 映射器,作用是加载sql的映射,有四种方式

  1. 使用类路径:<mapper resource="com/xxx/mapper/UserDao.xml"/>
  2. 使用完全限定资源定位符(URL): <mapper url="file:///user/xx/project/xxx/UserDao.xml"/>
  3. 使用映射器接口实现类的完全限定类名: <mapper class="com.xxx.UserDao"/>
  4. 使用包内的映射器接口实现全部注册为映射器: <package name="com.xxx.mapper"/>

基于xml复杂映射开发

准备:演示说明具体的xml复杂映射开发前,需要准备一下模拟信息

- 实体

- Mapper接口

  • 实体(对应数据库表)
public class User{
    private Integer id;
    private String userName;
    //一个用户,有多个订单(一对多)
    private List<Order> orderList;
    //用户角色(多对多)
    private List<Role> roleList;
}
public class Order{
    private Integer id;
    private Integer userId;
    private String orderTime;
    //一个订单,只有一个用户(一对一)
    private User user;
}
public class Role{
    private Integer id;
    private String roleName;
}
public class UserRole{
    private Integer userId
    private Integer roleid;
}
  • Mapper接口
public class OrderMapper{
    List<Order> findAll();
    //查询一对一
    List<Order> finUserAndOrder();
}
public class UserMapper{
    User findById(Integer userId);
    //查询一对多
    List<User> findAll();
    //查询多对对
    List<User> findAllUserAndRole();
}
public class RoleMapper{
    //查询多对对
    List<Role> findByUserId(Integer userId);
}

一对一查询

<mapper namespace="OrderMapper">
    <!--一对一映射配置-->
    <resultMap id="orderMap" type="Order">
        <result property="id" column="id"/>
        <result property="userId" column="userId"/>
        <result property="orderTime" column="orderTime"/>
        <!--
            这里配置User对象里面的user属性的User对象与表字段的映射关系
            实现把user和order的一对一关系映射
        -->
        <association property="user" javaType="User">
            <result property="id" column="userId"/>
            <result property="username" column="username"/>
        </association>
    </resultMap>

    <!--resultMap: 手动配置实体属性与表字段的映射关系-->
    <select id="finUserAndOrder" parameterType="Order" resultMap="orderMap">
        select * from order o,user u where o.userId = u.id
    </select>
</mapper>

一对多查询

从用户角度出发,查询一对多结果;

<mapper namespace="UserMapper">
    <!--一对多映射配置-->
    <resultMap id="userMap" type="User">
        <result property="id" column="id"/>
        <result property="username" column="username"/>
        <!--这里配置orderList属性的Order对象与表字段的映射关系-->
        <collection property="orderList" ofType="Order">
            <result property="id" column="oid"/>
            <result property="userId" column="userId"/>
            <result property="orderTime" column="orderTime"/>
        </collection>
    </resultMap>
    <!--resultMap: 手动配置实体属性与表字段的映射关系-->
    <select id="findAll" parameterType="User" resultMap="userMap">
        select *,o.id oid from user u left join order o on o.userId = u.id
    </select>
</mapper>

多对多查询

用户和角色的关系,就是多对多查询;

<mapper namespace="UserMapper">
    <!--多对多映射配置-->
    <resultMap id="userRoleMap" type="User">
        <result property="id" column="id"/>
        <result property="username" column="username"/>
        <!--这里配置roleList属性的Role对象与表字段的映射关系-->
        <collection property="roleList" ofType="Role">
            <result property="id" column="rid"/>
            <result property="roleName" column="roleName"/>
        </collection>
    </resultMap>
    <select id="findAllUserAndRole" parameterType="User" resultMap="userRoleMap">
        select u.*,r.*,r.id rid from user u 
            left join user_role ur on u.id = ur.userId
            left join role r on r.id = ur.roleId
    </select>
</mapper>

测试复杂映射

public static void main(String[] args){
    //获取配置输入流
    InputStream inputStream = Resources.getResourceAsSteam("splMapConfig.xml");
    //获取sql会话
    SqlSession sqlSession = SqlSessionFactoryBuilder.build(inputStream).openSession();
    UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
    //执行查询

    /*一对一*/
    List<Order> orderList = orderMapper.finUserAndOrder();
    for(Order order : orderList){
        System.out.println(order)
    }
    /*一对多*/
    List<User> userList = userMapper.findAll();
    for(User user : userList){
        System.out.println(user)
    }
    /*多对多*/
    List<User> userList = userMapper.findAllUserAndRole();
    for(User user : userList){
        System.out.println(user)
    }
    sqlSession.close();
}

Mybatis注解开发

常用注解:使用注解开发前,先介绍以下常用的注解

  • @Insert 新增
  • @Update 更新
  • @Delete 删除
  • @Select 查询
  • @Result 实现结果集封装。代替了xml中的和标签,有以下属性:
  1. column 数据库的字段名
  2. property 对应对象的属性名one 需要使用的@One注解 :@Result( one=@One )
  3. many 需要使用@Many注解:@Result( many=@Many )
  • @Results 可以与@Result一起使用,封装多个结果集
  • 代替了xml中的标签,也可以使用@Result集合,使用格式:
@Results({
      @Result(),@Result()
  })
  • @One 一对一结果集封装

代替了标签,是多表查询的关键,在注解中用来指定子查询返回单一对象。有以下属性:

  1. select 指定用来多表查询的 sqlmapper
@Result(column="",property="",one=@One(select=""))
  • @Many 一对多结果集封装

代替了标签,是多表查询的关键,再注解中用来指定子查询返回的对象集合。有以下属性:

  1. select 指定用来多表查询的 sqlmapper
@Result(column="",property="",one=@Many(select=""))

使用注解一对一查询

public class OrderMapper{
    //查询一对一
    @Select("select * from order")
    @Results({
        @Result(id=true,property="id",column="id"),
        @Result(property="userId",column="userId"),
        @Result(property="orderTime",column="orderTime")
        @Result(property="user",column="userId",
                javaType=User.class,
                one=@One(select="com.xxx.mapper.UserMapper.findById")
               )
    })
    List<Order> finUserAndOrder();
}
public class UserMapper{
    @Select("select * from user where id=#{userId}")
    User findById(Integer userId);
}

使用注解一对多查询

public class OrderMapper{    
    @Select("select * from order where userId=#{userId}")
    List<Order> findByUserId(Integer userId);
}
public class UserMapper{
    //查询一对多
    @Select("select * from user")
    @Results({
        @Result(id=true,property="id",column="id"),
        @Result(id=true,property="username",column="username"),
        @Result(property="orderList",column="id",
                javaType=List.class,
                many=@Many(select="com.xxx.mapper.OrderMapper.findByUserId")
    })
    List<User> findAllUserAndOrder();
}

使用注解多对多查询

public class UserMapper{
    //查询多对对
    @Select("select * from user")
    @Results({
        @Result(id=true,property="id",column="id"),
        @Result(property="username",column="username"),
        @Result(property="roleList",column="id",
               javaType=List.class,
               many=@Many(select="com.xxx.mapper.RoleMapper.findByUserId"))
    })
    List<User> findAllUserAndRole();
}
public class RoleMapper{
    //查询多对对
    @Select("select * from role r,user_role ur where r.id=ur.roleId and ur.userId = #{userId}")
    List<Role> findByUserId(Integer userId);
}

结语

以上是对mybatis的基础使用和高级用法,实际项目中,可以结合情况,使用xml查询或者使用两者结合查询都是可行的。

可以的话,麻烦“关注”一下哦。后续文章中,会继续介绍mybatis的缓存和插件机制。

快捷访问:Mybatis一级缓存和二级缓存

相关推荐

暗网是什么?到底有多可怕?(暗网有多可怕)

https://mp.weixin.qq.com/s/O7l4rveLnXLt-XE2A0WZ3g

“暗网”是什么,到底有多可怕,互联网的“另外一个世界”

来源成戈科技说悄悄告诉你何为“暗网”,暗网的用途是什么?到底多可怕?暗网的英文是“deepnet或deepweb”,也就是深网的意思,我们都知道,南北极的冰川看起来非常雄伟,但是你物理稍微懂一点你就...

什么是暗网?暗网有什么用?进来我告诉你

网的英文是“deepnet或deepweb”,也就是深网的意思,我们都知道,南北极的冰川看起来非常雄伟,但是你物理稍微懂一点你就会知道,我们看到的只是冰山的10%,还有90%在水面以下,很容易看出来,...

网工跳槽必备,2022年最新大厂高频技术面试真题整理

2022年金三银四正在进行,很多粉丝问我要网络工程师面试方面的资料,有在学校准备实习的,有已经工作准备跳槽的。我翻看最近的笔记,正好有整理一份今年大厂的面试题分享给大家。可以先说的是,国内的互联网面试...

三天吃透操作系统面试八股文(三天吃透计算机网络八股文)

操作系统的四个特性?并发:同一段时间内多个程序执行(与并行区分,并行指的是同一时刻有多个事件,多处理器系统可以使程序并行执行)...

掌握前端面试八股文,提升个人能力,实战面试必备!

前言:前端面试是每个前端开发者职业发展中的重要环节。掌握一些常见的前端面试题目,不仅能够在面试中表现出色,还能够提升自身的技术能力和知识广度。本文将为你介绍一些实用的前端面试题目,帮助你在面试中脱颖而...

进大厂必备的Java八股文大全(2022最强精简易懂版)

2022年秋招即将来临,很多同学会问Java面试八股文有必要背吗?答案是,必须背,博主是个三本,今年凭借这篇八股文斩获了多个大厂暑期实习offer,相信秋招一定也可以发挥重要作用。你可以讨厌这种模式,...

2022最新软件测试八股文,能不能拿心仪Offer就看你背得怎样了

前言鉴于目前测试就业越来越严峻,内卷也成了测试领域的代名词了。我的一个HR朋友告诉我,由于门槛较低,现在普通测试岗(偏功能)的投递比已经将近100,也就是一个岗位差不多有百分简历投进来。所以现在还想从...

《面试八股文》之Dubbo17卷(面试 八股文)

作者:moon原文:https://mp.weixin.qq.com/s/-kVf5qWqcw-4AJF7LL3uWw前言...

前端面试八股文?不存在的!(2021前端面试问题)

最近刷到一位前端小姐姐海外工作分享的视频,分享了她的求职,面试以及工作生活的感受,了解到海外求职面试的一个过程,其中我们经常聊的...

凭借这份《2022测试八股文》候选者逆袭面试官,offer拿到手软

《2023测试面试八股文》800道软件测试面试真题,高清打印版打包带走,横扫软件测试面试高频问题,涵盖测试理论、Linux、MySQL、Web测试、接口测试、App测试、Python、Selen...

面试常考八股文及算法(一)(八股文的要求)

define和const的区别1.define是预处理指令,用于创建符号常量。`const`是C和C++的关键字,用于创建具有常量值的变量,本质是只读变量。2.`define`在预处理阶...

面试必备(背)--计算机网络八股文系列

1.OSI七层、TCP/IP四层的关系和区别?七层模型,亦称OSI(OpenSystemInterconnection),它是一个七层的、抽象的模型体,不仅包括一系列抽象的术语或概念,也包括...

Java面试一定要坚持背的八股文!错过会很可惜!

很多人对java面试题都嗤之以鼻,认为无法衡量出一个程序员的真实水平。还有一部分原因,也是因为太难背了。那我们到底还要不要背?背!当然要背!但也不是死记硬背。在我们背诵的过程中,就把java的核心知识...

面试问八股文的公司都是垃圾?(八股文负面影响)

做医生的需要有医师资格证,做财务的有CPA证书,做教师的有教师资格证等等,做程序员的从来没听说过面试的时候需要你提供什么证书,既然没有可以证明从业能力的证书,那面试的时候如何来判断候选人的基本能力呢?...

取消回复欢迎 发表评论: