mybatis学习笔记8:注解开发

2023-11-18

文章目录

一、基于注解的开发环境搭建以及实现查询所有

1.定义主配置文件

mybatis的注解开发是对于映射配置文件这个层面来说的,所以仍然需要定义主配置文件,和前文基于xml配置方法和细节,和注意事项完全一致

  • SqlMapConfig.xml
<configuration>
    
    <properties  resource="jdbcConfig.properties">
    </properties>
    
    <!--使用typeAliases配置别名,它只能配置domain(实体类)中类的别名 -->
    <typeAliases>
        <!--typeAlias用于配置别名。type属性指定的是实体类全限定类名。alias属性指定别名,当指定了别名就再区分大小写
        用于指定要配置别名的包,当指定之后,该包下的实体类都会注册别名,并且类名就是别名,不再区分大小写-->
        <package name="com.xpt.domain"/>
    </typeAliases>
    
    <!--配置环境 default 和 id保持一致-->
    <environments default="mysql">
        <environment id="mysql">
            <!--配置事务类型-->
            <transactionManager type="JDBC"></transactionManager>
            <!--配置数据源信息-->
            <dataSource type="UNPOOLED">
                <!--连接数据库的四个基本信息-->
                <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>
        <!-- package标签是用于指定dao接口所在的包,当指定了之后就不需要在写mapper以及resource或者class了 -->
        <!--指定带有注解的dao接口所在位置-->
        <package name="com.xpt.dao"/>
    </mappers>

</configuration>

2.准备实体类和Dao接口

和前文使用的数据表,实体类保持一致
在这里插入图片描述

3.Dao接口定义findAll方法,以及添加注解

//    @Select(value = "select * from user")
    //只有一个参数时,value可以省略
    @Select("select * from user")
    List<User> findAll();

4.测试类定义方法测试

  • 代码
    public static void main(String[] args) throws Exception {

        //1.获取字节输入流
        InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.根据字节输入流构建 SqlSessionFactory
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        //3.利用factory生产一个SqlSession
        SqlSession sqlSession = factory.openSession();
        //4.利用sqlSession获取代理对象
        IUserDao userDao = sqlSession.getMapper(IUserDao.class);
        //5.利用代理对象 执行方法
        List<User> users = userDao.findAll();
        for (User user : users) {
            System.out.println(user);
        }
        //6.释放资源
        sqlSession.close();
        in.close();
    }
  • 结果:
    在这里插入图片描述
  • 上述就是基于注解开发的一个基本步骤
  • 下面 关注一些细节的问题

5.注解开发和基于xml的映射配置文件开发对比

在这里插入图片描述

6.注解开发的一个小细节

  • 只要使用的注解,就不能再建立对应的目录结构下建立IUserDao.xml配置文件了
  • 不然会报错
    在这里插入图片描述

二、基于注解开发的单表的CRUD

理解了前面的查询的过程,后面的内容都基本一致。

1.IUserDao的配置代码

    @Select("insert into user(username,address,sex,birthday)values(#{username},#{address},#{sex},#{birthday})")
    void saveUser(User user);

    @Select("update user set username=#{username},sex=#{sex},birthday=#{birthday},address=#{address} where id=#{id}")
    void  updateUser(User user);

    @Select("delete from user where id=#{id}")
    void deleteUser(Integer userId);

2.测试类的代码

public class AnnotationCRUDTest {
    private InputStream in;
    private SqlSessionFactory factory;
    private SqlSession sqlSession;
    private IUserDao userDao;

    @Before
    public void init() throws Exception{
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        factory = new SqlSessionFactoryBuilder().build(in);
        sqlSession = factory.openSession();
        userDao = sqlSession.getMapper(IUserDao.class);
    }

    @After
    public void destroy() throws Exception{
        sqlSession.commit();
        sqlSession.close();
        in.close();
    }

    @Test
    public void testSave(){
        User user = new User();
        user.setUsername("mybatis annotation");
        user.setAddress("唐人街");

        userDao.saveUser(user);

    }

    @Test
    public void testUpdate(){
        User user = new User();
        user.setId(63);

        user.setUsername("update mybatis annotation");
        user.setAddress("唐人街 50号");

        userDao.updateUser(user);

    }

    @Test
    public void testDelete(){


        userDao.deleteUser(63);

    }
}
  • 经过测试,均能完成通过

三、基于注解开发的单表查询的其他常用功能

1.IUserDao的配置代码


    @Select("select * from user where id = #{id}")
    User findById(Integer userId);


    @Select("select * from user where username like '%${value}%' ")
    List<User> findUserByName(String username);


    @Select("select count(*) from user ")
    int findTotalUser();

2.测试类的代码

    @Test
    public void testFindById(){
        User user = userDao.findById(57);
        System.out.println(user);
    }


    @Test
    public  void testFindByName(){
//        List<User> users = userDao.findUserByName("%mybatis%");
        List<User> users = userDao.findUserByName("mybatis");
        for(User user : users){
            System.out.println(user);
        }
    }

    @Test
    public  void testFindTotal(){
        int total = userDao.findTotalUser();
        System.out.println(total);
    }

四、使用注解实现复杂关系映射开发

1.当实体类的属性名和数据表的字段名不一致的解决方案

在基于xml的配置开发的时候,二者不一致的时候,使用的是一个map来解决,注解开发如何解决这个问题呢?

1.1先修改实体类的属性名,重新生成相关方法

1.2使用@Results和@Result这两个注解

  • 1.接口配置
  @Select("select * from user")
    @Results(value = {
            //id默认为false 这里指定为true是因为id为主键 column 数据表字段名 property 实体类属性名
            @Result(id = true,column = "id",property = "userId"),
            @Result(column = "username",property = "userName"),
            @Result(column = "address",property = "userAddress"),
            @Result(column = "sex",property = "userSex"),
            @Result(column = "birthday",property = "userBirthday")
    })

    List<User> findAll();
  • 2.执行testFindAll()方法
  @Test
    public  void testFindAll(){

        List<User> users = userDao.findAll();
        for(User user : users){
            System.out.println(user);
        }
    }
  • 3.结果:可以实现正常的结果
    在这里插入图片描述 - 4.测试testFindById()方法
    @Test
    public void testFindById(){
        User user = userDao.findById(57);
        System.out.println(user);
    }
  • 结果:没有封装成功,由于win10下mysql忽略大小写的缘故,显示了username
    在这里插入图片描述- 至于原因很简单,就是因为没有在该方法中进行相应的配置,那么问题来了,不可能每一个方法上都用那么大一串注解吧,
  • 所以基于注解的方式也可以使用userMap来完成一次定义,多处使用的效果

2.定义注解的时候,添加id属性值

在这里插入图片描述- 此时再测试findById()方法:就可以成功完成查询
在这里插入图片描述

3.注解开发实现多对一(一对一)的查询配置

这里同样使用用户和账户的实例来说明

3.1首选在账户实体类中建立映射属性


    //建立多对一(mybatis中称为 一对一)的映射 一个账户只能属于一个用户
    private User user;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

3.2IAccountDao的注解配置

    /**
     * 查询account的信息 并同时查询所属的用户信息
     * @return
     */
    @Select("select * from account")
    @Results(id = "accountMap", value={
            @Result(id = true,column = "id" ,property = "id"),
            @Result(column = "uid" ,property = "uid"),
            @Result(column = "money" ,property = "money"),
            //下面把user的信息也封装进来
            @Result(
                    property = "user",
                    column = "uid",//在user表中当然是使用uid进行查询
                    //使用注解 @one 来指定一对一的关系 select是在user表中查询的全限定名加方法名
                    //后面 fetchType指定加载类型 LAZY延迟加载 EAGER立即加载
                    one = @One(select = "com.xpt.dao.IUserDao.findById",fetchType = FetchType.EAGER)
            )}
    )
    List<Account> findAll();
  • 注意点:
    在这里插入图片描述

4.注解开发实现一对多

查询用户,并查询出用户下所有的账户信息

4.1实体类User中定义关系映射

    //一对多关系映射 一个用户下 有多个账户
    List<Account> accounts;

    public List<Account> getAccounts() {
        return accounts;
    }

4.2IUserDao完善注解配置

  /**
     * 查询所有用户 并同时查询对应的账户信息
     * @return
     */
//    @Select(value = "select * from user")
    //只有一个参数时,value可以省略
    @Select("select * from user")
    @Results(id = "userMap",value = {
            //id默认为false 这里指定为true是因为id为主键 column 数据表字段名 property 实体类属性名
            @Result(id = true,column = "id",property = "userId"),
            @Result(column = "username",property = "userName"),
            @Result(column = "address",property = "userAddress"),
            @Result(column = "sex",property = "userSex"),
            @Result(column = "birthday",property = "userBirthday"),
            @Result(
                    property = "accounts",//查询结果 封装到accounts属性
                    column = "id",//这里的id就是用户id
                    many = @Many(select = "com.xpt.dao.IAccountDao.findAccountByUid",
                            fetchType = FetchType.LAZY)
            )
    })
    List<User> findAll();

4.3测试:

  • 代码
    @Test
    public  void testFindAll(){

        List<User> users = userDao.findAll();
        for(User user : users){
            System.out.println("---用户查询信息---");
            System.out.println(user);
            System.out.println(user.getAccounts());

        }
    }

  • 结果:在这里插入图片描述

五、基于注解开发的二级缓存设置

1.一级缓存都是默认开启的

  • 代码
    @Test
    public void testFindById(){
        User user1 = userDao.findById(42);
        System.out.println(user1);


        User user2 = userDao.findById(42);
        System.out.println(user2);

        System.out.println(user1 == user2);


    }
  • 结果:
    在这里插入图片描述

2二级缓存配置

2.1主配置文件开启全局二级缓存

 <!--配置开启二级缓存-->
    <settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>

2.2IUserDao开启二级缓存配置

在这里插入图片描述

2.3测试方法

public class SecondLevelCacheTest {
    private InputStream in;
    private SqlSessionFactory factory;
//    private SqlSession sqlSession;
//    private IUserDao userDao;

    @Before
    public void init() throws Exception{
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        factory = new SqlSessionFactoryBuilder().build(in);
//        sqlSession = factory.openSession();
//        userDao = sqlSession.getMapper(IUserDao.class);
    }

    @After
    public void destroy() throws Exception{
//        sqlSession.commit();
//        sqlSession.close();
        in.close();
    }





    @Test
    public void testFindById(){
        SqlSession sqlSession = factory.openSession();
        IUserDao userDao = sqlSession.getMapper(IUserDao.class);
        User user1 = userDao.findById(42);
        System.out.println(user1);

        //释放一级缓存
        sqlSession.close();

        //再次打开缓存
        SqlSession sqlSession1 = factory.openSession();
        IUserDao userDao1 = sqlSession1.getMapper(IUserDao.class);
        User user2 = userDao1.findById(42);
        System.out.println(user2);

        sqlSession1.close();

        System.out.println(user1 == user2);

    }

2.4结果

  • 只完成一次数据库查询,第二次在缓存中查询

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

mybatis学习笔记8:注解开发 的相关文章

  • Java 利用hutool工具实现导出excel并合并单元格

    Java 利用hutool工具实现导出excel并合并单元格 controller层调用service 就一个核心方法 没错就下面这个代码就能实现了 前提是项目里面要引用hutool包 把我这个复制到项目里面然后改掉字段应该能直接跑起来的
  • SQL Server统计数据库表空间大小和数据量

    SQL Server统计数据库表空间大小和数据量 在大数据环境中 对于SQL Server数据库的管理和优化是非常重要的 其中一个关键任务是统计数据库中各个表的空间大小和数据量 通过了解每个表所占用的存储空间 可以进行容量规划 性能优化和资
  • 虚拟机上的Ubuntu开机显示“无法应用原保存的显示器配置”

    如图 解决方法 删除monitors xml 文件 rm config monitors xml
  • pdf模板,java替换变量

    开发十年 就只剩下这套Java开发体系了 gt gt gt 1 创建pdf 现在word中创建模板 输出为pdf文件2 pdf 2 java项目引入依赖
  • 单片机时间戳转换

    看了网上的例程 大多繁琐 直接利用time h里的库函数进行转换即可 include
  • windows上传文件到ubuntu

    进入putty目录下 运行pscp 然后pscp 目标文件 Linux用户名 IP地址 目标文件夹 输入linux的登陆密码即可 more than one remote source not supported 出现这种情况是由空格导致的
  • Linux内核的编译、安装、调试

    这里写目录标题 编译安装内核 下载内核 安装依赖 更改 config 编译内核 安装 首先安装模块 安装内核 更改引导 更改 grub 重启 其他操作 清理内核源目录 卸载安装的内核 修改内核配置菜单实现对新加入内核源码的控制 常见问题 1
  • 8-13外部排序-败者树

    败者树是树形选择排序的一种变体 可视为一棵完全二叉树 通过败者树 可以在k个归并段中选出最小关键字所需要的关键字对比次数更少 绿色为叶子结点 存放初始数据 黑色为失败结点 蓝色为胜出结点 一 基本过程 以下按从小到大的方式构建 1 从8个归
  • Nor Flash,Nand Flash

    文章目录 1 Nor Flash 使用场景 2 Nand Flash 使用场景 3 读写速度对比 4 成本与容量 1 Nor Flash 使用场景 对于大多数应用较为简单的场景 比如 MCU 其内置的 Flash 就是使用的是 Nor Fl
  • python基础开发篇3——线上环境部署Django项目

    文章目录 一 基本了解 二 打包本地项目 三 服务器环境准备 四 安装web服务 4 1 使用uwsgi代理 4 2 使用nginx代理 推荐 五 部署daphne 一 基本了解 部署思路 Nginx服务接收浏览器的动态请求 再通过uwsg
  • 前端上传图片,Python后端接收

    前端代码 h1 Image Upload h1
  • 题目:洛谷1088 火星人(排列组合问题)

    题目描述 人类终于登上了火星的土地并且见到了神秘的火星人 人类和火星人都无法理解对方的语言 但是我们的科学家发明了一种用数字交流的方法 这种交流方法是这样的 首先 火星人把一个非常大的数字告诉人类科学家 科学家破解这个数字的含义后 再把一个
  • homework03

    1 编写一个程序来读入不指定个数的整数 然后决定已经读取的整数中有多少个正数和多少个负数 并计算这些输入值 不统计0 的总和 最终得出它们的平均值 这个程序以输入值0来结束 使用浮点数显示这个平均值 a 0 b 0 sum 0 count
  • Python之ML--机器学习分类算法

    Python之ML 机器学习分类算法 介绍最早以算法方式描述的分类机器学习算法 感知器 perceptron 和自适应线性神经元 adaptive linear neuron 我们将使用python循序渐进地实现一个感知器 并且通过训练使其
  • VSCode与PyCharm提示unresolved import解决方案

    问题描述 在VScode或者pyharm中采用python import自定义模块是 有时会显示unresolved import警告并且 无法跳转到自定义模块函数定义 出现问题的原因 没有安装import对应的模块 import的文件夹没
  • 使用STM32的TIMER进行外部计数

    使用ETR引脚的输入信号作为计数时钟 本例程使用Timer 2 其ETR输入引脚为PA1 该引脚工作模式为输 入模式 Timer的工作模式为从模式 另外使用PC6输出一模拟方波时钟信号 测试时将PC6与PA1短接 用户也可另外连接一个时钟信
  • 简述反射机制

    一 什么是反射 1 1 反射 所谓框架的灵魂 框架 半成品软件 可以在框架的基础上进行软件开发 简化代码 反射 将类的各个组成部分封装为其他对象 反射机制 简单来说反射就是在程序运行期间 动态的获取类或者对象中的属性 什么是动态获取 反射的
  • Swift语法学习--类(class)

    文章目录 类 初始化及实例 类的引用 reference 特征 类和结构体比较 类属性的set和get方法解析 类属性的willSet和didSet方法解析 类的下标 类方法和静态方法 将一个类的实例作为另一个类的属性 类的继承 父类在实例
  • MATLABdiag()用法

    1 提取矩阵的对角线元素 设A为m n矩阵 diag A 函数用于提取矩阵A主对角线元素 产生一个具有min m n 个元素的列向量 diag A k 提取矩阵A第k条对角线的元素 产生一个列向量 注意 矩阵的对角线 与主对角线平行 往上为
  • Unity核心5——Tilemap

    Tilemap 一般称之为瓦片地图或者平铺地图 是 Unity2017 中新增的功能 主要用于快速编辑 2D 游戏中的场景 通过复用资源的形式提升地图多样性 工作原理就是用一张张的小图排列组合为一张大地图 它和 SpriteShape 的异

随机推荐

  • android Scrollview里的内容不停留在顶部的问题

    先说明一下 任何一个页面都应该按照布局的先后顺序来显示 我这出现的问题就是 Scrollview里面嵌套Listview的头布局一进来看不见了 直接被Listview把焦点给抢了 最先显示的是Listview的item部分 直接上图 解决代
  • React中的“计算属性”

    React中的 计算属性 相信许多学习过vue的小伙伴对计算属性都不陌生吧 计算属性能帮我们数据进行一些计算操作 计算属性是依赖于data里面的数据的 在vue中只要计算属性依赖的data值发生改变 则计算属性就会调用 那React中也有计
  • gsaop 有头文件生成wsdl文件

    gsoap ns service name name area gsoap ns service style rpc gsoap ns service encoding encoded gsoap ns service namespace
  • SSM框架之MyBatis(二)--多表查询及查询结果映射

    使用MyBatis这一强大的框架可以解决很多赋值的问题 其中对于子配置文件中的小细节有很多需要注意的地方 使用这个框架后主要就是对于配置文件的编写和配置 今天我写了一个多表查询 表的基本结构如下 用户表t user 用户编号uid 账号ac
  • CNN中特征融合的一些策略

    Introduction 特征融合的方法很多 如果数学化地表示 大体可以分为以下几种 X Y textbf X textbf Y X Y X
  • 12. Xaml Calendar控价 时间控件-->像挂历

    1 运行图片 2 运行源码 a xaml 源码
  • 通信原理复习(四)——基带数字信号的表示和传输

    数字信号传输的标志 1 除去直流分量和频率很低的分量 2 在接收端得到的每个码元的起止时刻信息 3 使信号的频谱和信道的传输特性相匹配 波形 1 单极性波形 只适合用导线连接的各点之间做近距离传输 0和 V V 2 双极性波形 取 V和 V
  • AD导入3D模型

    我之前写过一篇文章也是说AD的3D模型的 http blog csdn net tq384998430 article details 78614014 介绍的是使用AD自带的功能绘制3D模型 但是这样绘制出来的形状并不是很好看 如果导入元
  • el-table的无限滚动(效果比虚拟滚动更优)

    步骤 1 前端安装 save el table infinite scrol npm install save el table infinite scroll 2 全局引用 在main js中引用 import Vue from vue
  • C语言实现八进制转十进制

    八进制转十进制 include
  • java类的生命周期

    如图 1 加载 我们编写一个java的源文件 经过编译后生成一个后缀名为 class的文件 这结合四字节码文件 java虚拟机就识别这种文件 java的生命周期就是class文件从加载到消亡的过程 关于加载 其实 就是将源文件的class文
  • 关键元器件选型设计指引--通用逻辑器件(逻辑IC)

    1 物料分类 标准逻辑器件 标准数字逻辑IC集成电路可以从工艺 功能和电平三个方面划分 列表所示 注 常见的逻辑电路有54军用系列和74商用系列 两者电路功能一致 本文仅讨论74系列 按照制造工艺特点分类 工艺 逻辑器件产品族 优点 不足
  • sublime-text3-自定义代码补全

    自定义代码补全 打开sublime text3 选择菜单栏 工具 gt 新代码段 按以下模板填充 content 在CDATA中填补全内容 tabTrigger 触发代码 scope 文件类型 description 描述信息 下例为 输入
  • Kafka一致性

    一 存在的一致性问题 1 生产者和Kafka存储一致性的问题 即生产了多少条消息 就要成功保存多少条消息 不能丢失 不能重复 更重要的是不丢失 其实就是要确保消息写入成功 这可以通过acks 1来保证 保证所有ISR的副本都是一致的 即一条
  • CSP 202212-1 现值计算

    答题 主要就是 include
  • “无法从静态上下文中引用非静态变量,非静态方法”原因及解决

    1 原因 1 用static修饰的方法为静态方法 修饰变量则为静态变量 又分别叫做类方法或者类变量 这些从属于类 是类本身具备的 没有实例也会存在 2 而非静态方法和变量的存在依赖于对象 是对象的属性 需要先创建实例对象 然后通过对象调用
  • ★SQL注入漏洞(7)SQL注入高级篇

    分析目标防火墙并且跳过 1 直接拉黑ip类防火墙 2 过滤删除相应字符的防火墙 1 waf注释符号过滤 例题 Sqli labs T23 特点 注释符 被过滤掉了 绕过方法 逻辑上补全闭合即可 多加一次url编码只是更安全的绕过 selec
  • Redis系列1——数据类型和常用数据操作

    一 redis基础知识 客户端和服务器命令 默认端口号6379 服务器命令 redis server redis windows conf 设置服务一直开启 首先进入redis安装目录 然后执行 redis server service i
  • android so 调试

    安卓调试 环境 tool JDK 8X 之前用15版本的 monitor一直无法启动 链接 https pan baidu com s 12LUwB7ZOVEcblAzkO8hxyA 提取码 5lw0 monitor bat 流程 开启调试
  • mybatis学习笔记8:注解开发

    文章目录 一 基于注解的开发环境搭建以及实现查询所有 1 定义主配置文件 2 准备实体类和Dao接口 3 Dao接口定义findAll方法 以及添加注解 4 测试类定义方法测试 5 注解开发和基于xml的映射配置文件开发对比 6 注解开发的