精品专题:
01.《C语言从不挂科到高绩点》课程详细笔记
https://blog.csdn.net/yueyehuguang/category_12753294.html?spm=1001.2014.3001.5482
02. 《SpringBoot详细教程》课程详细笔记
https://blog.csdn.net/yueyehuguang/category_12789841.html?spm=1001.2014.3001.5482
03.《SpringBoot电脑商城项目》课程详细笔记
https://blog.csdn.net/yueyehuguang/category_12752883.html?spm=1001.2014.3001.5482
04.《VUE3.0 核心教程》课程详细笔记
https://blog.csdn.net/yueyehuguang/category_12769996.html?spm=1001.2014.3001.5482
================================
|| 持续分享系列教程,关注一下不迷路 ||
|| 视频教程:墨轩大楼 ||
================================
🌲 简介
MyBatis注解方式就是将SQL语句直接写在接口上,代替映射文件中的标签配置的SQL语句。这种方式的优点是,对于需求简单的系统,效率较高。缺点是,当SQL有变动时,修改重新编译代码。使用注解就是在接口方法基础上添加需要的注解,并写上SQL语句@Select、@Insert、@Update、@Delete这四个基本注解的参数可以是字符串数组。
🌲 环境准备
🌾 数据表
DROP TABLE IF EXISTS `emp`;
CREATE TABLE `emp` (
`empno` int NOT NULL AUTO_INCREMENT,
`ename` varchar(20) DEFAULT NULL,
`job` varchar(20) DEFAULT NULL,
`manager` int DEFAULT NULL,
`hiredate` date DEFAULT NULL,
`salary` double DEFAULT NULL,
`comm` double DEFAULT NULL,
`deptno` int DEFAULT NULL,
PRIMARY KEY (`empno`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8mb3;
-- ----------------------------
-- Records of emp
-- ----------------------------
INSERT INTO `emp` VALUES ('1', '郭靖', 'clerk', '4', '2022-02-03', '7000', '2000', '2');
INSERT INTO `emp` VALUES ('2', '黄蓉', 'saleman', '4', '2023-02-01', '6000', '5000', '3');
INSERT INTO `emp` VALUES ('3', '江湖骗子', 'saleman', '4', '2023-02-18', '7000', '3000', '3');
INSERT INTO `emp` VALUES ('6', '孙尚香', '业务人员', '3', '2023-05-23', '5000', '0', null);
INSERT INTO `emp` VALUES ('7', '赵四', '舞者', '1', '2023-05-30', '5000', '5000', '4');
INSERT INTO `emp` VALUES ('8', '张飞', '开发', '1', '2023-05-30', '8000', '2000', '3');
INSERT INTO `emp` VALUES ('9', '关羽', '运维', '1', '2023-05-30', '6000', '4000', '3');
🌾 新建项目

🌾 导入依赖
需要将mybatis的依赖导入到pom.xml中,依赖如下:
<dependencies>
<!-- mybatis依赖-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.7</version>
</dependency>
<!-- mysql依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
</dependency>
<!--lombok依赖-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.3.0</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.6</version>
</dependency>
</dependencies>
🌾 创建包目录
在resources目录中创建mappers目录用来存放映射文件,在项目中新建entity包和dao包分别存放实体类和映射器接口,结构如下图:

图片中的log4j.properties日志文件暂时用不上,可以不用管它,也不用添加进来。
🌾 添加配置文件
在resources目录中添加链接数据库的数据源配置文件db.properties,内容如下:
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/study?serverTimezone=UTC
user=root
password=123456
在dao目录中新建映射器接口,EmpDao.java,内容如下:
package com.moxuan.mybatis_annotation.dao;
public interface EmpDao {
}
在resources下的mappers文件中添加映射器接口,内容如下:
<?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">
<!-- 此处的namespace需要对应上dao包中的数据操作接口-->
<mapper namespace="com.moxuan.mybatis_annotation.dao.EmpDao">
</mapper>
在entity包中新建Emp实体类,代码如下:
package com.moxuan.mybatis_annotation.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.sql.Date;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Emp {
private Integer empno;
private String ename;
private String job;
private Integer manager;
private Date hiredate;
private Double salary;
private Double comm;
private Integer deptno;
}
在resources目录中添加mybatis配置文件mybatis-config,内容如下:
<?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>
<properties resource="db.properties"></properties>
<!--常规配置-->
<settings>
<!--允许自动生成主键:配合映射文件-->
<setting name="useGeneratedKeys" value="true"/>
<setting name="logImpl" value="STDOUT_LOGGING" />
</settings>
<typeAliases>
<package name="com.moxuan.mybatis_annotation.entity"/>
</typeAliases>
<!--配置分页插件-->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!--指定数据库方言,可以不用配置,默认识别具体的数据库管理系统-->
<property name="helperDialect" value="mysql"/>
<!--
pageSizeZero:默认值为 false,当该参数设置为 true 时,
如果 pageSize=0 或者 RowBounds.limit = 0
就会查询出全部的结果(相当于没有执行分页查询,但是返回结果仍然是 Page 类型)。
-->
<property name="pageSizeZero" value="true"/>
<!--
reasonable:分页合理化参数,默认值为false。当该参数设置为 true 时,
pageNum<=0 时会查询第一页, pageNum>pages(超过总数时),
会查询最后一页。默认false 时,直接根据参数进行查询。
-->
<property name="reasonable" value="true"/>
</plugin>
</plugins>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<!-- 数据源配置 -->
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${user}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mappers\EmpMapper.xml"></mapper>
</mappers>
</configuration>
🌲 具体实现
🌾 添加@Mapper注解
在映射器接口EmpDao上方添加@Mapper ,Mybatis注解主要是通过@Mapper 注解来实现的,添加了这个注解后,程序就会从这个接口中寻找对应的sql语句注解。代码如下:
package com.moxuan.mybatis_annotation.dao;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface EmpDao {
}
🌾 添加Mybatis工具类
package com.moxuan.mybatis_annotation.util;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
public class MyBatisUtil {
private static SqlSessionFactory factory;
static{
// 在静态代码块下,factory只会被创建一次
try {
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
factory = new SqlSessionFactoryBuilder().build(is);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 获取sqlSession对象
* @return
*/
public static SqlSession getSession(){
return factory.openSession(false);// true 为自动提交事务
}
/**
* 关闭sqlSession对象
* @param session
*/
public static void closeSqlSession(SqlSession session){
if(session!=null){
session.close();
}
}
}
🌾 @Select 查询注解
在映射器接口的方法上添加@Select注解,写上对应的查询sql语句,当调用方法时会触发注解中的sql语句做查询操作,代码如下:
@Mapper
public interface EmpDao {
@Select("select * from emp")
List<Emp> findAll();
}
在test目录中编写测试类进行测试:
import com.moxuan.mybatis_annotation.dao.EmpDao;
import com.moxuan.mybatis_annotation.entity.Emp;
import com.moxuan.mybatis_annotation.util.MyBatisUtil;
import org.apache.ibatis.session.SqlSession;
import org.junit.jupiter.api.Test;
import java.util.List;
public class MybatisTest {
@Test
public void test01(){
SqlSession session = MyBatisUtil.getSession();
EmpDao dao = session.getMapper(EmpDao.class);
System.out.println("==========查询所有的员工信息===========");
List<Emp> emps_01 = dao.findAll();
for (Emp emp :emps_01){
System.out.println(emp);
}
}
}
运行结果:

🌾 @Insert 注解添加数据
@Insert 注解可以用于在方法上添加向数据库新增数据的sql语句,在EmpDao中添加新增数据的方法,代码如下:
当sql语句中需要使用参数,而这些参数是方法参数对象的属性时,可以将方法参数对象用@Param 取一个别名,然后通过别名调用属性,来给sql语句设置参数
@Insert("insert into emp (ename,job) values(#{e.ename},#{e.job})")
void addEmp(@Param("e") Emp emp);
在test中添加测试方法:
@Test
public void testAdd(){
SqlSession session = MyBatisUtil.getSession();
EmpDao dao = session.getMapper(EmpDao.class);
System.out.println("==========添加员工===========");
Emp emp = new Emp();
emp.setEname("狗蛋");
emp.setJob("掏粪男孩");
dao.addEmp(emp);
session.commit();
System.out.println("数据添加成功");
}
运行结果:

🌾 @Update 修改数据
@Update 注解可以用于在方法上添加修改数据库数据的sql语句,在EmpDao中添加修改数据的方法,代码如下:
@Update("update emp set job=#{e.job} where empno=#{e.empno}")
void updateEmp(@Param("e") Emp emp);
测试方法如下:
@Test
public void testUpdate(){
SqlSession session = MyBatisUtil.getSession();
EmpDao dao = session.getMapper(EmpDao.class);
System.out.println("==========修改员工===========");
Emp emp = new Emp();
emp.setEmpno(9);
emp.setJob("掏粪男孩");
dao.addEmp(emp);
session.commit();
System.out.println("数据添加成功");
}
运行效果:

🌾 @Delete删除数据
@Delete 注解可以用于在方法上添加删除数据库数据的sql语句,在EmpDao中添加删除数据的方法,代码如下:
@Delete("delete from emp where empno=#{id}")
void deleteEmp(@Param("id")int empno);
测试方法如下:
@Test
public void testDelete(){
SqlSession session = MyBatisUtil.getSession();
EmpDao dao = session.getMapper(EmpDao.class);
System.out.println("==========删除员工===========");
int empno = 9;
dao.deleteEmp(empno);
session.commit();
System.out.println("数据删除成功");
}
运行效果:

🌾 注解与映射文件搭配使用
由于注解开发是将所有的sql语句以字符串的形式写在方法的上面,有些情况就不适合放在注解中,比如动态sql的拼接以及关联映射、resultMap的配置等等。通常我们会将resultMap以及关联映射等相关信息配置到映射文件中,然后再使用注解去调用。
我们先看看使用注解在sql语句中拼接动态SQL是什么样的,比如下面我们想要实现一个动态修改的SQL语句注解,写法如下:
@Update({"<script>"+
"update emp " +
" <set>" +
" <if test='e.ename!=null'> ename=#{e.ename},</if> " +
" <if test='e.job!=null'> job=#{e.job},</if> " +
" <if test='e.manager!=null'> manager=#{e.manager},</if> " +
" <if test='e.salary!=null'> salary=#{e.salary},</if> " +
" <if test='e.comm!=null'> comm=#{e.comm},</if> " +
" <if test='e.deptno!=null'> deptno=#{e.deptno},</if> " +
" </set> " +
" where empno=#{e.empno} " +
"</script>"})
void updateEmpSql(@Param("e")Emp emp);
- 在注解中使用动态sql时需要添加需要将sql语句写在 { } 中
- 在sql语句外面需要包裹一层<script></script>告诉mybatis这是一个动态sql脚本,而不是一个普通sql语句。
编写测试方法:
@Test
public void testUpdateEmp(){
SqlSession session = MyBatisUtil.getSession();
EmpDao dao = session.getMapper(EmpDao.class);
Emp emp = new Emp();
emp.setEmpno(3);
emp.setEname("心肝小宝贝儿");
System.out.println("====修改之前====");
List<Emp> empList = dao.findAll();
for(Emp e:empList){
System.out.println(e);
}
dao.updateEmpSql(emp);
session.commit();// 修改数据库数据之后,需要提交事务
System.out.println("====修改之后====");
empList = dao.findAll();
for(Emp e:empList){
System.out.println(e);
}
}
可以看到这种方式虽然可以达到我们想要的效果,但是,拼接复杂,容易出错。
还有一种情况,当数据库字段和实体类属性不一致的时候,我们无法将数据查出来,这个时候就需要用到resultMap去做映射。这种情况在字符串中拼接也会比较麻烦,我们一般的做法,可以将resultmap相关映射写在映射文件中,然后再到映射器接口中使用@ResultMap注解引用。
比如:现在的employee对应emp表,其属性如下所示:
package com.moxuan.mybatis_annotation.entity;
import lombok.Data;
import java.sql.Date;
@Data
public class Employee {
private Integer p_empno;
private String p_ename;
private String p_job;
private Integer p_manager;
private Date p_hiredate;
private Double p_salary;
private Double p_comm;
private Integer p_deptno;
}
这个时候如果我们按照以前的方式编写sql语句,代码如下:
@Select("select * from emp")
List<Employee> getEmployees();
此时去测试程序
@Test
public void test02(){
SqlSession session = MyBatisUtil.getSession();
EmpDao dao = session.getMapper(EmpDao.class);
System.out.println("==========查询所有的员工信息===========");
List<Employee> emps_01 = dao.getEmployees();
for (Employee emp :emps_01){
System.out.println(emp);
}
}
就会发现测试结果都为null,

此时,我们可以去映射文件中进行配置,使用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">
<!-- 此处的namespace需要对应上dao包中的数据操作接口-->
<mapper namespace="com.moxuan.mybatis_annotation.dao.EmpDao">
<resultMap id="empMap" type="employee">
<id column="empno" property="p_empno"></id>
<result column="ename" property="p_ename"></result>
<result column="job" property="p_job"></result>
<result column="manager" property="p_manager"></result>
<result column="hiredate" property="p_hiredate"></result>
<result column="salary" property="p_salary"></result>
<result column="comm" property="p_comm"></result>
<result column="deptno" property="p_deptno"></result>
</resultMap>
</mapper>
上面我们将resultMap的id设置为了empMap,这个在映射器sql语句注解下使用@ResultMap("resultMap的id")去使用映射文件中对应的resultMap,代码如下:
@Select("select * from emp")
@ResultMap("empMap")
List<Employee> getEmployees();
再次运行,结果如下:

🌲 总结
- 注解方式适用于SQL语句简单时,复杂的动态SQL语句还是建议在映射文件中配置
- 使用注解方式时,如果sql语句中需要传参,那么需要在接口方法中使用@Param 去指定参数的名字
- 使用注解方式时,如果需要用到动态sql语句时,一定要使用 { "<script>sql语句</script>"}此种格式,将sql语句包裹,否则mybatis不会将其作为动态sql语句去解析。
- 注解方式和映射文件方式可以搭配使用,合理搭配能提升开发效率
64万+

被折叠的 条评论
为什么被折叠?



