百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

MyBatis精讲(八)MyBatis注解用法之DAO数据注解对象实战代码详解

bigegpt 2024-08-21 12:03 2 浏览

大家好,我是 @老K玩代码。

本期是关于MyBatis基础教程讲义的最后一讲了,我们要来说说MyBatis的一个特性——注解。

MyBatis里有很多功能注解,我们可以通过这些注解,实现各种映射器接口,替代mapper.xml类文件的作用。

到底应该怎么做呢?我们一起开看一下。

之前的内容可以通过下面的链接查看:

  • 老K玩代码:MyBatis精讲(一)MyBatis基础配置及持久层连接创建代码实战
  • 老K玩代码:MyBatis精讲(二)常用工具MyBatisUtils类的实现
  • 老K玩代码:MyBatis精讲(三)一篇文章让你学会如何用MyBatis获取数据
  • 老K玩代码:MyBatis精讲(四)查询数据方法精讲及实战代码集合
  • 老K玩代码:MyBatis精讲(五)CRUD操作及实战代码精讲
  • 老K玩代码:MyBatis精讲(六)一对多数据查询实战分享
  • 老K玩代码:MyBatis精讲(七)动态SQL查询方法实战代码讲解

这一讲对的内容有点多,建议可以先收藏起来,慢慢读,慢慢消化。

一、准备工作

通过maven新建项目,以及在pom文件里配置依赖库相关的步骤就不介绍了,有需要的可以看《MyBatis精讲(一)MyBatis基础配置及持久层连接创建代码实战》。

项目配置好后,我们先把数据库通过sql语句的方式导入到项目里:

DROP TABLE IF EXISTS `employee`;
CREATE TABLE `employee`  (
  `id` int UNSIGNED NOT NULL AUTO_INCREMENT,
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
  `depart` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
  `salary` decimal(10, 2) NOT NULL,
  `age` int NOT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

DROP TABLE IF EXISTS `department`;
CREATE TABLE `department`  (
  `did` int UNSIGNED NOT NULL AUTO_INCREMENT,
  `depart` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  `member` int NULL DEFAULT NULL,
  PRIMARY KEY (`did`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

INSERT INTO `employee` VALUES (5001, '赵乾', '销售部', 6000.00, 28);
INSERT INTO `employee` VALUES (5002, '孙礼', '销售部', 7000.00, 34);
INSERT INTO `employee` VALUES (6001, '周武', '技术部', 6500.00, 27);
INSERT INTO `employee` VALUES (6002, '郑望', '技术部', 7500.00, 40);

INSERT INTO `department` VALUES (1, '销售部', 5);
INSERT INTO `department` VALUES (2, '技术部', 6);

在项目路径下创建一个dao目录(本例中的完整路径为./src/main/java/koder/mybatis/dao)。

DAOData Annotation Objects的首字母,表示数据注解对象实体。

然后在mybatis-config.xml进行如下配置(注:mybatis-config.xml文件路径参考《MyBatis精讲(一)MyBatis基础配置及持久层连接创建代码实战》中的内容。)

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <setting name="mapUnderscoreToCamelCase" value="True"/>
    </settings>
    <environments default="dev">
        <environment id="dev">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url"
                          value="jdbc:mysql://localhost:3306/javasql?useUnicode=true&characterEncoding=utf-8"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <package name="koder.mybatis.dao"/>
    </mappers>
</configuration>
  • <package>是用来配置映射器包的标签,一般是包含映射器接口的目录位置。

二、查询数据

我们首先在映射器包(本例中该路径为./src/main/java/koder/mybatis/dao)下新建一个接口类——HRDao.java,并编写以下内容:

  • HRDao.java
import koder.mybatis.dto.EmployeeDTO;
import koder.mybatis.entity.Employee;
import org.apache.ibatis.annotations.*;

import java.util.List;

public interface HRDao {
    @Select("select * from employee where id = #{value}")
    public Employee selectById(@Param("value") Integer id);
}
  • koder.mybatis.dto.EmployeeDTO是后面案例会用到的数据传输对象类,在这里先导入;
  • org.apache.ibatis.annotations是mybatis的注解类;
  • @Select注解,定义sql查询语句;
  • 对于sql查询语句中的可变参数,用#{value}表示,这里的value是自定义的,可以是任何变量名称;
  • @Param注解定义变量参数,便是该参数对应在sql查询语句中的名称,本例中表示java方法参数id就是sql语句中的value值。

这样,一个数据注解对象、也就是注解映射器就写好了,接下来我们编写测试用例:

  • MyBatisTest.java(文件路径和基本配置参见《MyBatis精讲(三)一篇文章让你学会如何用MyBatis获取数据》)
@Test
public void TestDaoSelectById() {
    SqlSession sqlSession = null;
    try {
        sqlSession = MyBatisUtils.openSession();
        HRDao hrDao = sqlSession.getMapper(HRDao.class);
        Employee emp = hrDao.selectById(6001);
        System.out.println(emp.getName());
    }catch (Exception e) {
        e.printStackTrace();
    } finally {
        MyBatisUtils.closeSession(sqlSession);
    }
}
  • 通过SqlSessiongetMapper方法获取数据注解对象类,本例中为HRDaoclass
  • 调用HRDao的查询方法,就能直接对应映射的sql语句,执行查询,返回对应数据类型;

上述代码运行后的结果为:

周武

三、插入数据

插入数据的映射接口,可以用@Insert注解器实现:

  • HRDao.java
@Insert("insert into employee(name, depart, salary, age) values (#{name}, #{depart}, #{salary}, #{age})")
@SelectKey(statement = "select last_insert_id()", keyProperty = "id", keyColumn = "id", before = false, resultType = Integer.class)
public int insert(Employee employee);
  • 上述代码内容,应写在HRDao接口内,是HRDao的内部方法;
  • @Insert可以接收sql的插入语句,如果传入的是实体对象(如Employee),@Insert注解器会自动将实体类的成员变量通过驼峰转换传入sql语句;
  • @SelectKey相当于MyBatis的xml语法中的<selectKey>功能一致,定义的sql语句会和主语句一起被执行。statement参数接收sql语句,keyProperty接受java类中的成员变量名,keyColumn接受数据库中的字段列名,before表示该语句是在主语句之前还是之后执行,resultType是将执行后得到的数据存入那个数据类型中;

然后在MyBatisTest.java中写入测试用例:

  • MyBatisTest.java
@Test
public void TestDaoInsert() {
    SqlSession session = null;
    try {
        session = MyBatisUtils.openSession();
        Employee employee = new Employee();
        employee.setAge(34);
        employee.setDepart("技术部");
        employee.setName("储纬");
        employee.setSalary(7700.0f);
        HRDao hrDao = session.getMapper(HRDao.class);
        hrDao.insert(employee);
        session.commit();
        System.out.println(employee.getId());
    } catch (Exception e) {
        if (session != null) {
            session.rollback();
        }
        throw new RuntimeException(e);
    } finally {
        MyBatisUtils.closeSession(session);
    }
}
  • 由于映射器接口中insert方法传入的参数是Employee,所以我们先实例化一个Employee实例,传入到HRDao.insert方法中;
  • insert方法使用事务机制,所以完成方法调用后,需要commit才能生效,并且失败后需要rollback

执行上述代码后,得到结果如下:

6003

并且,查看数据库也能发现新的数据被录入成功!


四、修改数据

编写映射接口。

  • HRDao.java
@Update("update employee set name = #{name}, depart = #{depart}, salary = #{salary}, age = #{age} where id = #{id}")
public int update(Employee employee);
  • @Update是更新数据的注解方法,语法特征与@Insert类似。

而测试用例编写如下:

  • MyBatis.java
@Test
public void TestDaoUpdate() {
    SqlSession session = null;
    try {
        session = MyBatisUtils.openSession();
        HRDao hrDao = session.getMapper(HRDao.class);
        Employee employee = hrDao.selectById(6001);
        employee.setSalary(7900f);
        hrDao.update(employee);
        session.commit();
        System.out.println(employee.getId());
    } catch (Exception e) {
        if (session != null) {
            session.rollback();
        }
        throw new RuntimeException(e);
    } finally {
        MyBatisUtils.closeSession(session);
    }
}
  • 由于修改数据,需要先从数据库中获取,我们用查询方法select ById获取Employee实例;
  • 调用HRDaoupdate方法,执行更新数据的操作;
  • 由于是事务机制,所以需要添加commitrollback语句;

执行上述代码后,可以发现数据库中对应条目的薪酬已改为7900.00


五、删除数据

编写映射接口:

  • HRDao.java
@Delete("delete from employee where id = #{value}")
public int delete(@Param("value") Integer id);
  • @Delete是删除数据的注解类,注意要点与@Update@Insert一致;
  • 参数用@Param进行映射匹配;

测试用例编写如下:

  • MyBatis.java
@Test
public void TestDaoDelete() {
    SqlSession session = null;
    try {
        session = MyBatisUtils.openSession();
        HRDao hrDao = session.getMapper(HRDao.class);
        hrDao.delete(6003);
        session.commit();
    } catch (Exception e) {
        if (session != null) {
            session.rollback();
        }
        throw new RuntimeException(e);
    } finally {
        MyBatisUtils.closeSession(session);
    }
}

执行上述代码后,可以发现,之前插入的数据“储纬”已被删除;


六、自定义ResultMap链表查询

之前讲过通过mapper.xml语法连表查询需要用到resultMap标签,那么,如果用数据注解对象,如何解决链表查询的问题呢?

首先在HRDao.java编写接口:

  • HRDao.java
@Select("select e.*, d.* from employee e, department d where e.depart = d.depart")
@Results({
        @Result(property="employee.id", column="id", id = true),
        @Result(property="employee.name", column="name"),
        @Result(property="employee.salary", column="salary"),
        @Result(property="employee.depart", column="depart"),
        @Result(property="employee.depart", column="depart"),
        @Result(property="employee.age", column="age"),
        @Result(property="department.did", column="did"),
        @Result(property="department.member", column="member")
})
public List<EmployeeDTO> selectDTO();
  • 我们先用@Select编写链表查询的语句;
  • 利用@Results注解定义当前方法的结果类;
  • @Results中通过@Result对数据属性进行映射,参数property接收java类中的成员变量,参数column接收数据库中的字段列名,id表示该字段是否作为id索引;

测试用例:

  • MyBatis.java
@Test
public void TestDaoSelectDto() {
    SqlSession session = null;
    try {
        session = MyBatisUtils.openSession();
        HRDao hrDao = session.getMapper(HRDao.class);
        List<EmployeeDTO> emps = hrDao.selectDTO();
        for (EmployeeDTO emp: emps) {
            System.out.println(emp.getEmployee().getName() + "所在的部门有"+emp.getDepartment().getMember() + "人。");
        }
    } catch (Exception e) {
        throw new RuntimeException(e);
    } finally {
        MyBatisUtils.closeSession(session);
    }
}
  • DTO链表查询和普通查询代码逻辑一样;

执行上述代码,获得如下结果:

赵乾所在的部门有5人。
孙礼所在的部门有5人。
周武所在的部门有6人。
郑望所在的部门有6人。

以上,就是MyBatis的数据注解对象DAO常见的使用方法。

DAO相比起xml映射器,代码的可读性更强,对java工程师更友好,而且java编译器能提供语法支持,更便于工程师们排查错误。

熟练掌握DAO映射接口的写法,对高效使用MyBatis有很大的帮助!

感谢你看到这里。

如果你对老K分享的内容有任何疑问,欢迎随时在评论区留言或者私信我。

正在学习的小伙伴记得给老K一个赞哦,你的支持是我持续输出课程内容最大的动力。

结束语

我是专注于开发领域的@老K玩代码,会持续生产关于如何学习编程语言的优质内容。

如果你对编程和项目开发有兴趣,可以关注我。


#头条创作挑战赛#

相关推荐

悠悠万事,吃饭为大(悠悠万事吃饭为大,什么意思)

新媒体编辑:杜岷赵蕾初审:程秀娟审核:汤小俊审签:周星...

高铁扒门事件升级版!婚宴上‘冲喜’老人团:我们抢的是社会资源

凌晨两点改方案时,突然收到婚庆团队发来的视频——胶东某酒店宴会厅,三个穿大红棉袄的中年妇女跟敢死队似的往前冲,眼瞅着就要扑到新娘的高额钻石项链上。要不是门口小伙及时阻拦,这婚礼造型团队熬了三个月的方案...

微服务架构实战:商家管理后台与sso设计,SSO客户端设计

SSO客户端设计下面通过模块merchant-security对SSO客户端安全认证部分的实现进行封装,以便各个接入SSO的客户端应用进行引用。安全认证的项目管理配置SSO客户端安全认证的项目管理使...

还在为 Spring Boot 配置类加载机制困惑?一文为你彻底解惑

在当今微服务架构盛行、项目复杂度不断攀升的开发环境下,SpringBoot作为Java后端开发的主流框架,无疑是我们手中的得力武器。然而,当我们在享受其自动配置带来的便捷时,是否曾被配置类加载...

Seata源码—6.Seata AT模式的数据源代理二

大纲1.Seata的Resource资源接口源码2.Seata数据源连接池代理的实现源码3.Client向Server发起注册RM的源码4.Client向Server注册RM时的交互源码5.数据源连接...

30分钟了解K8S(30分钟了解微积分)

微服务演进方向o面向分布式设计(Distribution):容器、微服务、API驱动的开发;o面向配置设计(Configuration):一个镜像,多个环境配置;o面向韧性设计(Resista...

SpringBoot条件化配置(@Conditional)全面解析与实战指南

一、条件化配置基础概念1.1什么是条件化配置条件化配置是Spring框架提供的一种基于特定条件来决定是否注册Bean或加载配置的机制。在SpringBoot中,这一机制通过@Conditional...

一招解决所有依赖冲突(克服依赖)

背景介绍最近遇到了这样一个问题,我们有一个jar包common-tool,作为基础工具包,被各个项目在引用。突然某一天发现日志很多报错。一看是NoSuchMethodError,意思是Dis...

你读过Mybatis的源码?说说它用到了几种设计模式

学习设计模式时,很多人都有类似的困扰——明明概念背得滚瓜烂熟,一到写代码就完全想不起来怎么用。就像学了一堆游泳技巧,却从没下过水实践,很难真正掌握。其实理解一个知识点,就像看立体模型,单角度观察总...

golang对接阿里云私有Bucket上传图片、授权访问图片

1、为什么要设置私有bucket公共读写:互联网上任何用户都可以对该Bucket内的文件进行访问,并且向该Bucket写入数据。这有可能造成您数据的外泄以及费用激增,若被人恶意写入违法信息还可...

spring中的资源的加载(spring加载原理)

最近在网上看到有人问@ContextConfiguration("classpath:/bean.xml")中除了classpath这种还有其他的写法么,看他的意思是想从本地文件...

Android资源使用(android资源文件)

Android资源管理机制在Android的开发中,需要使用到各式各样的资源,这些资源往往是一些静态资源,比如位图,颜色,布局定义,用户界面使用到的字符串,动画等。这些资源统统放在项目的res/独立子...

如何深度理解mybatis?(如何深度理解康乐服务质量管理的5个维度)

深度自定义mybatis回顾mybatis的操作的核心步骤编写核心类SqlSessionFacotryBuild进行解析配置文件深度分析解析SqlSessionFacotryBuild干的核心工作编写...

@Autowired与@Resource原理知识点详解

springIOCAOP的不多做赘述了,说下IOC:SpringIOC解决的是对象管理和对象依赖的问题,IOC容器可以理解为一个对象工厂,我们都把该对象交给工厂,工厂管理这些对象的创建以及依赖关系...

java的redis连接工具篇(java redis client)

在Java里,有不少用于连接Redis的工具,下面为你介绍一些主流的工具及其特点:JedisJedis是Redis官方推荐的Java连接工具,它提供了全面的Redis命令支持,且...