Mybatis基础学习之使用注解开发

前言

小伙伴们,大家好,我是狂奔の蜗牛rz,当然你们可以叫我蜗牛君,我是一个学习Java半年多时间的小菜鸟,同时还有一个伟大的梦想,那就是有朝一日,成为一个优秀的Java架构师。

这个Mybatis基础学习系列是用来记录我学习Mybatis框架基础知识的全过程 (这个系列是参照B站狂神的Mybatis最新教程来写的,由于是之前整理的,但当时没有发布出来,所以有些地方可能有错误,希望大家能够及时指正!)


之后我将尽量以两天一更的速度更新这个系列,还没有学习Mybatis3框架的小伙伴可以参照我的博客学习一下;当然学习过的小伙伴,也可以顺便跟我一起复习一下基础。最后,希望能够和大家一同进步吧!加油吧!少年们!

特别提醒:如果对Mybatis基础学习系列感兴趣,可以阅读本系列往期博客:
第一篇Mybatis基础学习之初识Mybatis
第二篇Mybatis基础学习之第一个Mybatis程序
第三篇Mybatis基础学习之CRUD增删改查
第四篇Mybatis基础学习之万能的Map和模糊查询
第五篇Mybatis基础学习之配置解析(上篇)
第六篇Mybatis基础学习之配置解析(下篇)
第七篇Mybatis基础学习之使用ResultMap解决字段名不一致
第八篇Mybatis基础学习之日志工厂的简单使用
第九篇Mybatis基础学习之数据分页的简单使用


今天我们来到了Mybatis基础学习的第九站:使用注解开发。废话不多说,让我们开始今天的学习内容吧。

9.使用注解开发

9.1 面向接口编程

在之前的Java基础学习中,我们都知道Java语言一门面向对象的编程语言,很多相关书籍和资深程序员也会经常强调面向对象编程的重要性。在Java基础学习中,我们也接触到了接口的概念,而在真正的开发中,很多时候也会选择面向接口编程,那么为什么要选择面向接口编程呢?

9.1.1 为什么要选择面向接口编程?

选择面向接口的根本原因是

  • 为了解耦,提高可拓展和复用性
  • 分层开发中,上层不用管具体的实现,都遵守公共的标准,使得开发变得很容易,规范性更好

9.1.2 什么是面向接口编程?

一个面向对象的系统中,系统的各种功能是由许许多多的不同对象协作完成的;这种情况下,各个对象内部是如何实现相对来说就不那么重要了

各个对象之间的协作关系成为系统设计的关键,小到不同类之间的通信,大到各模块之间的交互,这不仅是在设计之初需要着重考虑的,也是系统设计的主要工作内容,而面向接口编程就是指按照这种思想来编程。

9.1.3 关于接口的理解

  • 接口从更深层次的理解,应是定义 (规范和约束) 与实现 (名实分离) 的分离

  • 接口的本身反映了系统设计人员对系统的抽象理解

  • 接口应有两类

    第一类:对一个个体的抽象,它可对应成为一个抽象体(abstract class)

    第二类:对一个个体某一方面的抽象,即形成一个抽象面(interface)

  • 一个个体可能有多个抽象面抽象体抽象面有区别的

9.1.4 三个面向区别

  • 面相对象:考虑问题时,以对象为单位,考虑它的属性及方法
  • 面向过程:考虑问题时,以一个具体的流程 (事务过程) 为单位,考虑它的实现
  • 面向接口接口设计非接口设计针对复用技术而言的,与面向对象 (或者面向过程) 不是一个问题,更多的体现是对系统整体的架构

9.2 使用注解开发

本质反射机制实现

底层动态代理

9.2.1 创建编写实体类和工具类

1.编写User实体类
// User实体类
public class User {
    
    private int id; // 用户编号
    private String name; // 用户名
    private String password; // 密码
    
    // User实体类的无参构造方法
    public User() {
    }
    
    // User实体类的有参构造方法
    public User(int id, String name, String password) {
        this.id = id;
        this.name = name;
        this.password = password;
    }
    
    /**
     * 字段对应的get和set方法
     */
    
    public int getId() {
        return id;
    }
    
    public void setId(int id) {
        this.id = id;
    }
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public String getPassword() {
        return password;
    }
    
    public void setPassword(String password) {
        this.password = password;
    }
    
    // 生成对应的toString方法
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
    
}
2.编写MyBatisUtils工具类
/**
 * SqlSessionFactoryBuilder (建造工厂)
 * --> sqlSessionFactory (生产sqlSessio)
 * --> sqlSession
 */
public class MybatisUtils {
    
    // 获取静态变量sqlSessionFactory
    private static SqlSessionFactory sqlSessionFactory;
    
    // 静态方法体
    static {
        try {
            String resource = "mybatis-config.xml";
            // 读取配置文件
            InputStream inputStream = Resources.getResourceAsStream(resource); 
            // 获取工厂
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
   /**
    * SqlSession提供了在数据库执行SQL命令所需的所有方法
    */
   public static SqlSession getSqlSession() {
       return sqlSessionFactory.openSession();
   }
    
}

9.2.2 编写接口和核心配置文件

1.编写UserMapper接口
  • 注解在接口的方法上实现
public interface UserMapper {
    
    /**
     * 使用Select注解: 查询所有用户信息
     */
    @Select("Select * from user")
    List<User> getUsers();
    
}
2.编写db.properties配置文件
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8
username=root
pwd=123456
3.编写mybatis-config.xml配置文件

注意我们必须要将接口注册绑定到我们的核心配置文件中!

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!-- configuration: 核心配置文件 -->
<configuration>
    <!-- 引入外部配置文件: 优先使用外部配置文件 -->
    <properties resource="db.properties"></properties>
    <!-- 设置标准日志输出 -->
    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    
    <!-- 通过给包起别名 -->
    <typeAliases>
        <package name="com.kuang.pojo"/>
    </typeAliases>
    
    <!-- 设置默认环境为开发环境 -->
    <environments default="development">
        <!-- 设置一道环境为开发环境 -->
        <environment id="development">
            <!-- transactionManager: 表示事务管理器, 而MyBatis的默认管理器是JDBC -->
            <transactionManager type="JDBC"/>
            <!-- dataSource: 表示数据源,主要作用: 连接数据库(MyBatis的默认数据源类型是POOLED,也就是有池的连接) -->
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${pwd}"/>
            </dataSource>
        </environment>
    </environments>
    
    <!-- 绑定接口: 使用class文件绑定注册 -->
    <mappers>
        <mapper class="com.kuang.dao.UserMapper"/>
    </mappers>
    
</configuration>

9.2.3 编写测试类和查看测试结果

1.编写UserMapperTest测试类
public class UserMapperTest {
    
    @Test
    public void test() {
        // 获取sqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        // 获取mapper接口类: 底层主要使用反射,通过反射来获取包的全类名
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        //调用getUsers方法
        List<User> users = mapper.getUsers();
        // 使用foreach循环遍历数组
        for (User user : users) {
            System.out.println(user);
        }
        // 关闭sqlSession
        sqlSession.close();
    }
    
}
2.测试结果

在这里插入图片描述

结果虽然测试成功,并没有报错,但仔细观察结果后发现password的值却为null!

9.2.4 注解开发的优缺点

优点使用注解来映射简单语句,会使代码显得更加简洁

缺点对于稍微复杂一点的语句,Java注解就力不从心了,并且会显得更加混乱

因此,如果需要完成很复杂的事情,最好使用xml来映射语句

9.2.5 使用断点解析原理

1.设置断点和Debug测试
  • 首先在获取用户信息这行设置断点,然后在test()方法旁右击选择Debug测试

在这里插入图片描述

2.测试结果分析

在这里插入图片描述

通过sqlSession获取变量后,mapper再次获取调用sqlSession,而mapper中的mapperInterface就是mapper接口,在mapperInterface下找到了com.kuang.dao.UserMapper

sqlSession拿到数据库配置

mapperInterface获取接口对象

methodCache缓存

9.3 拓展知识

9.3.1 代理模式

在这里插入图片描述

9.3.2 MyBatis执行流程

在这里插入图片描述

9.4 使用注解实现增删改查

9.4.1 使用注解实现查询用户

1.修改MyBatisUtils工具类
  • 可以在工具类创建的时候实现自动提交
/**
 * SqlSessionFactoryBuilder (建造工厂)
 * --> sqlSessionFactory (生产sqlSessio)
 * --> sqlSession
 */
public class MybatisUtils {
    
    // 获取静态变量sqlSessionFactory
    private static SqlSessionFactory sqlSessionFactory;
    
    // 静态方法体
    static {
        try {
            String resource = "mybatis-config.xml";
            // 读取配置文件
            InputStream inputStream = Resources.getResourceAsStream(resource); 
            // 获取工厂
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
   /**
    * SqlSession 提供了在数据库执行 SQL 命令所需的所有方法
    */
   public static SqlSession getSqlSession() {
       // 设置参数为true,实现自动提交
       return sqlSessionFactory.openSession(true);
   }
    
}
2.修改UserMapper接口
2-1 正常测试
public interface UserMapper {
    
    /**
     *  使用Select注解:通过id查询指定用户信息
     * 方法存在多个参数,所有的参数前面必须加上 @Param("属性名") 注解
     */
    @Select("Select * from user where id = #{id}")
    User getUserById(@Param("id") int id);
    
}
2-2 将id改为id2
  • @Param注解中的值id修改为id2
public interface UserMapper {
    
    /**
     * 使用Select注解:通过查询指定用户信息
     * 方法存在多个参数,所有的参数前面必须加上 @Param("属性名") 注解
     */
    @Select("Select * from user where id = #{id}")
    User getUserById(@Param("id") int id2);
}
  • 方法参数中的id修改为id2
public interface UserMapper {
    
    /**
     * 使用Select注解:通过查询指定用户信息
     * 方法存在多个参数,所有的参数前面必须加上 @Param("属性名") 注解
     */
    @Select("Select * from user where id = #{id}")
    User getUserById(@Param("id2") int id);
    
}
3.编写UserMapperTest测试类
public class UserMapperTest {
    
    @Test
    public void getUserById() {
        // 获取sqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        // 获取mapper接口类(底层主要使用反射,通过反射来获取包的全类名)
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        // 调用getUserById方法获取用户信息
        User userById = mapper.getUserById(1);
        // 打印查询到的用户信息
        System.out.println(userById);
        // 关闭sqlSession
        sqlSession.close();
    }
    
}
4.测试结果
4-1 正常测试结果

在这里插入图片描述

4-2 将id改为id2
  • @Param注解中的值id修改为id2

在这里插入图片描述

测试结果报错参数id找不到!

  • 方法参数中的id修改为id2

在这里插入图片描述

结果测试成功!

因此,@Select注解中的id与@Param注解中的id要一致!

9.4.2 使用注解实现增加用户

1.修改UserMapper接口
public interface UserMapper {
    
    /** 
    * 使用Insert注解:增加用户信息
    */
    @Insert("Insert into user(id,name,pwd) values(#{id},#{name},#{password})")
    int addUser(User user);
    
}
3.编写UserMapperTest测试类
public class UserMapperTest {
    
    @Test
    public void addUser() {
        // 获取sqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        // 获取mapper接口类:底层主要使用反射,通过反射来获取包的全类名
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        // 调用addUser方法并设置返回的结果集:实现用户信息的增加
        int result = mapper.addUser(new User(6,"陈奕迅","cyx123456"));
        // 判断结果集的值是否大于0
        if (result>0) {
            System.out.println("插入成功!");
        }
        // 关闭sqlSession
        sqlSession.close();
    }
    
}
4.正常测试结果
  • 查看控制台输出
    在这里插入图片描述
  • 查看数据库信息

在这里插入图片描述

结果成功插入一条用户信息!

5.Debug测试结果
  • int result这行设置断点,点击addUser()方法旁的Debug测试

在这里插入图片描述

  • 可以看到autoCommit的值由默认的false变为了true

在这里插入图片描述

因为在Mybatis工具类中已经设置了自动提交事务,因此测试方法中就不需要再次设置了,但是一般不建议设置自动提交事务,因为这样容易出现错误!

9.4.3 使用注解实现修改用户

2.修改UserMapper接口
public interface UserMapper {
    
    /**
     * 使用Update注解:修该指定用户信息
     */
    @Update("Update user set name = #{name},pwd = #{password} where id = #{id}")
    int updateUser(User user);  
    
}
3.编写UserMapperTest测试类
public class UserMapperTest {
    
    @Test
    public void updateUser() {
        // 获取sqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        // 获取mapper接口类(底层主要使用反射,通过反射来获取包的全类名)
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        // 调用updateUser方法, 实现插入用户信息
         mapper.updateUser(new User(6,"张惠妹","zhm123456"));
        // 关闭sqlSession
        sqlSession.close();
    }
    
}
4.测试结果
  • 查看控制台输出

在这里插入图片描述

  • 查看数据库信息

在这里插入图片描述

结果成功更新一条用户信息!

9.4.4 使用注解实现删除用户

2.修改UserMapper接口
public interface UserMapper {
    
    /**
     * 使用Delete注解:删除用户信息
     * @Delete注解中的uid要与@Param注解中的uid一致
     */
    @Delete("Delete from user where id = #{uid}")
    int deleteUser(@Param("uid") int id);
    
}
3.编写UserMapperTest测试类
public class UserMapperTest {
    
    @Test
    public void deleteUser() {
        // 获取sqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        // 获取mapper接口类(底层主要使用反射,通过反射来获取包的全类)
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        // 调用updateUser方法, 实现插入用户信息
        mapper.deleteUser(4);
        // 关闭sqlSession
        sqlSession.close();
    }
    
}
4.测试结果
  • 查看控制台输出

在这里插入图片描述

  • 查看数据库信息

在这里插入图片描述

结果成功删除id为4的用户信息!

9.5.5 关于@Param()注解

  • 基本类型的参数或者String类型,需要加上
  • 引用类型不需要加
  • 如果只有一个基本类型的话,可以忽略,但是建议加上
  • 在SQL中引用就是这里的@Param注解中设定的属性名!

9.5.6 #{} 和 ${} 区别

  • 一般使用 #{},能够很大程度上防止SQL注入!
  • ${} 方式无法防止SQL注入
  • $ 一般用于传入数据库对象,比如数据库表名
  • 能用 #{} 时尽量用 #{}

好了,今天的有关 使用注解开发 的学习就到此结束啦。欢迎小伙伴们积极学习和讨论,喜欢的可以给蜗牛君点个关注,顺便来个一键三连。我们下期见,拜拜啦!


参考视频链接【狂神说Java】Mybatis最新完整教程IDEA版通俗易懂

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

狂奔の蜗牛rz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值