😀前言
在当今的开发环境中,数据库的操作显得尤为重要和基础。MyBatis作为一个优秀的持久层框架提供了多种方式来实现CRUD操作,帮助开发者更方便、更灵活地与数据库交互。在本教程中,我们将首先通过MyBatis的原生API来探讨基本的数据库操作,然后转向更高级、更简洁的注解方式来实现CRUD功能。同时,我们也将展示如何在MyBatis的配置文件中注册注解类,以及如何创建并运行测试来验证我们的实现。
🧑个人简介:大家好,我是尘觉,希望我的文章可以帮助到大家,您的满意是我的动力😉😉
技术特点
封装Sqlsession到执行器+ Mapper 接口和Mapper.xml + MapperBean + 动态代理 代理Mapper 的方法
❤️🔥MyBatis深入探索:原生API与注解方式实现CRUD操作
😀MyBatis-原生的 API 调用
原生的 API 快速入门需求
● 在前面项目的基础上,将增删改查,使用 MyBatis 原生的 API 完成,就是直接通过
SqlSession 接口的方法来完成
1. 增加 2. 删除
3. 修改 4. 查询
为了大家的观看我把基于xml的配置和类也展示了如果你想要详细的观看可以看 连接这个博客
创建Monster
package com.wyxedu.entity; import java.util.Date; /** * Monster 和 monster表有对应关系 * 体现OOP */ //解读 //1. 一个普通的Pojo类 //2. 使用原生态的sql语句查询结果还是要封装成对象 //3. 要求大家这里的实体类属性名和表名字段保持一致。 public class Monster { //属性-和表字段有对应关系 private Integer id; private Integer age; private String name; private String email; private Date birthday; private double salary; private Integer gender; public Monster() { } public Monster(Integer id, Integer age, String name, String email, Date birthday, double salary, Integer gender) { this.id = id; this.age = age; this.name = name; this.email = email; this.birthday = birthday; this.salary = salary; this.gender = gender; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public double getSalary() { return salary; } public void setSalary(double salary) { this.salary = salary; } public Integer getGender() { return gender; } public void setGender(Integer gender) { this.gender = gender; } @Override public String toString() { return "Monster{" + "id=" + id + ", age=" + age + ", name='" + name + '\'' + ", email='" + email + '\'' + ", birthday=" + birthday + ", salary=" + salary + ", gender=" + gender + '}'; } }
创建MonsterMapper接口
package com.wyxedu.mapper; import com.wyxedu.entity.Monster; import java.util.List; /** * 1. 这是一个接口 * 2. 该接口用于声明操作monster表的方法 * 3. 这些方法可以通过注解或者xml文件来实现 */ public interface MonsterMapper { //添加monster public void addMonster(Monster monster); //根据id删除一个Monster public void delMonster(Integer id); //修改Monster public void updateMonster(Monster monster); //查询-根据id public Monster getMonsterById(Integer id); //查询所有的Monster public List<Monster> findAllMonster(); }
创建MonsterMapper.xml
<?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"> <!--解读 1. 这是一个mapper xml 文件 2. 该文件可以去实现对应的接口的方法 3. namespace 指定该xml文件和哪个接口对应!!! --> <mapper namespace="com.wyxedu.entity.Monster"> <!--配置addMonster 1. id="addMonster" 就是接口的方法名 2. parameterType="com.wyxedu.entity.Monster" 放入的形参的类型 3. 注意"com.wyxedu.entity.Monster" 可以简写 4. 写入sql语句=> 建议,现在sqlyog 写完成-测试通过,再拿过来 5. (`age`, `birthday`, `email`, `gender`, `name`, `salary`) 表的字段 6. (#{age}, #{birthday}, #{email}, #{gender}, #{name}, #{salary}) 是从传入的monster对象属性值 7. 这里 #{age} age 对应monster对象的属性名,其它一样 --> <insert id="addMonster" parameterType="Monster" useGeneratedKeys="true" keyProperty="id"> INSERT INTO `monster` (`age`, `birthday`, `email`, `gender`, `name`, `salary`) VALUES (#{age}, #{birthday}, #{email}, #{gender}, #{name}, #{salary}) </insert> <!--配置/实现delMonster方法 1. 这里 java.lang.Integer 这是Java类型, 可以简写成 Integer 2. 这里写入delete --> <delete id="delMonster" parameterType="Integer"> DELETE FROM `monster` WHERE id = #{id} </delete> <!--配置实现 updateMonster 1. com.wyxedu.entity.Monster 可以简写,. --> <update id="updateMonster" parameterType="Monster"> UPDATE `monster` SET `age`=#{age} , `birthday`= #{birthday}, `email` = #{email}, `gender` = #{gender} , `name`= #{name}, `salary` = #{salary} WHERE id = #{id} </update> <!--配置/实现getMonsterById--> <select id="getMonsterById" resultType="Monster"> SELECT * FROM `monster` WHERE id = #{id} </select> <!--配置/实现findAllMonster--> <select id="findAllMonster" resultType="Monster"> SELECT * FROM `monster` </select> </mapper>
配置mybits的xml
注意这个是全部的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> <!--引入外部的jdbc.properties--> <properties resource="jdbc.properties"/> <!--配置MyBatis自带的日志输出-查看原生的sql--> <settings> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings> <!--配置别名--> <typeAliases> <!--<typeAlias type="com.wyxedu.entity.Monster" alias="Monster"/>--> <!-- 如果一个包下有很多的类,我们可以直接引入包,这样 该包下面的所有类名,可以直接使用 --> <package name="com.wyxedu.entity"/> </typeAliases> <environments default="development"> <environment id="development"> <!--配置事务管理器--> <transactionManager type="JDBC"/> <!--配置数据源 解读 1. 我们使用外部的properties文件来设置相关的值 2. 这个属性文件,需要统一的放在 resources目录/类加载路径 3. 关于属性文件,在讲解java基础-集合 --> <dataSource type="POOLED"> <!--配置驱动--> <!--<property name="driver" value="com.mysql.jdbc.Driver"/>--> <property name="driver" value="${jdbc.driver}"/> <!--配置连接mysql-url 解读: 1. jdbc:mysql 协议 2. 127.0.0.1:3306 : 指定连接mysql的ip+port 3. mybatis: 连接的DB 4. useSSL=true 表示使用安全连接 5. & 表示 & 防止解析错误 6. useUnicode=true : 使用unicode 作用是防止编码错误 7. characterEncoding=UTF-8 指定使用utf-8, 防止中文乱码 8. 温馨提示:不要背,直接使用即可 --> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.user}"/> <property name="password" value="${jdbc.pwd}"/> </dataSource> </environment> </environments> <!--说明 1. 这里我们配置需要关联的Mapper.xml 2. 这里我们可以通过菜单 Path from source root --> <mappers> <!--<mapper resource="com/wyxedu/mapper/MonsterMapper.xml"/>--> <!--解读 1. 如果是通过注解的方式,可不再使用 MonsterMapper.xml 2. 但是需要在mybatis-config.xml注册/引入含注解的类 3. 如果没有引入,不能使用 --> <!--<mapper class="com.wyxedu.mapper.MonsterAnnotation"/>--> <!-- 解读 1. 当一个包下有很多的Mapper.xml文件和基于注解实现的接口时, 为了方便,我们可以以包方式进行注册 2. 将下面的所有xml文件和注解接口 都进行注册 --> <package name="com.wyxedu.mapper"/> </mappers> </configuration>
创建MyBatisUtils
package com.wyxedu.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; /** * MyBatisUtils 工具类,可以得到SqlSession */ public class MyBatisUtils { //属性 private static SqlSessionFactory sqlSessionFactory; //编写静态代码块-初始化sqlSessionFactory static { try { //指定资源文件, 配置文件mybatis-config.xml String resource = "mybatis-config.xml"; //获取到配置文件mybatis-config.xml 对应的inputStream //这里说明:加载文件时,默认到resources目录=>运行后的工作目录target-classes InputStream resourceAsStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); System.out.println("sqlSessionFactory=" + sqlSessionFactory.getClass()); } catch (IOException e) { e.printStackTrace(); } } //编写方法,返回SqlSession对象-会话 public static SqlSession getSqlSession() { return sqlSessionFactory.openSession(); } }
原生的 API 快速入门-代码实现
创建MyBatisNativeTest类
package com.wyxedu.mapper; import com.wyxedu.entity.Monster; import com.wyxedu.util.MyBatisUtils; import org.apache.ibatis.session.SqlSession; import org.junit.Before; import org.junit.Test; import java.util.Date; import java.util.List; public class MonsterMapperTest { //属性 private SqlSession sqlSession; private MonsterMapper monsterMapper; /** * 解读 * 1. 当方法标注 @Before, 表示在执行你的目标测试方法前,会先执行该方法 */ //编写方法完成初始化 @Before public void init() { //获取到sqlSession sqlSession = MyBatisUtils.getSqlSession(); //获取到到MonsterMapper对象 class com.sun.proxy.$Proxy7 代理对象 //, 底层是使用了动态代理机制, 后面我们自己实现mybatis底层机制时,会讲到 monsterMapper = sqlSession.getMapper(MonsterMapper.class); System.out.println("monsterMapper=" + monsterMapper.getClass()); } @Test public void addMonster() { for (int i = 0; i < 2; i++) { Monster monster = new Monster(); monster.setAge(10 + i); monster.setBirthday(new Date()); monster.setEmail("kate@qq.com"); monster.setGender(1); monster.setName("大象精-" + i); monster.setSalary(1000 + i * 10); monsterMapper.addMonster(monster); System.out.println("添加对象--" + monster); System.out.println("添加到表中后, 自增长的id=" + monster.getId()); } //如果是增删改, 需要提交事务 if(sqlSession != null) { sqlSession.commit(); sqlSession.close(); } System.out.println("保存成功..."); } @Test public void delMonster() { monsterMapper.delMonster(2); if(sqlSession != null) { sqlSession.commit(); sqlSession.close(); } System.out.println("删除成功..."); } @Test public void updateMonster() { Monster monster = new Monster(); monster.setAge(50); monster.setBirthday(new Date()); monster.setEmail("king3@qq.com"); monster.setGender(0); monster.setName("老鼠精-01"); monster.setSalary(2000); monster.setId(3); monsterMapper.updateMonster(monster); if(sqlSession != null) { sqlSession.commit(); sqlSession.close(); } System.out.println("修改成功..."); } @Test public void getMonsterById() { Monster monster = monsterMapper.getMonsterById(3); System.out.println("monster=" + monster); if(sqlSession != null) { sqlSession.close(); } System.out.println("查询成功~"); } @Test public void findAllMonster() { List<Monster> monsters = monsterMapper.findAllMonster(); for (Monster monster : monsters) { System.out.println("monster-" + monster); } if(sqlSession != null) { sqlSession.close(); } System.out.println("查询成功~"); } }
使用 sqlSession 原生的 API 调用我们编写的方法[了解]
创建myBatisNativeCrud
package com.wyxedu.mapper; import com.wyxedu.entity.Monster; import com.wyxedu.util.MyBatisUtils; import org.apache.ibatis.session.SqlSession; import org.junit.Before; import org.junit.Test; import java.util.List; /** * MyBatisNativeTest: 演示使用MyBatis原生API操作 */ public class MyBatisNativeTest { //属性 private SqlSession sqlSession; //编写方法完成初始化 @Before public void init() { //获取到sqlSession sqlSession = MyBatisUtils.getSqlSession(); //sqlSession 返回的对象是 DefaultSqlSession System.out.println("sqlSession--" + sqlSession.getClass()); } //使用sqlSession原生的API调用我们编写的方法[了解] @Test public void myBatisNativeCrud() { //添加 /** * * @Override * public int insert(String statement, Object parameter) { * return update(statement, parameter); * } * * statement: 就是接口方法-完整声明 * parameter: 入参 */ //Monster monster = new Monster(); //monster.setAge(100); //monster.setBirthday(new Date()); //monster.setEmail("kate2@qq.com"); //monster.setGender(0); //monster.setName("大象精-100"); //monster.setSalary(10000); // //int insert = // sqlSession.insert("com.wyxdu.mapper.MonsterMapper.addMonster", monster); // //System.out.println("insert---" + insert); //删除 //int delete = sqlSession.delete("com.wyxdu.mapper.MonsterMapper.delMonster", 11); //System.out.println("delete--" + delete); //修改 //Monster monster = new Monster(); //monster.setAge(20); //monster.setBirthday(new Date()); //monster.setEmail("kate3@qq.com"); //monster.setGender(1); //monster.setName("牛魔王-100"); //monster.setSalary(1000); //monster.setId(10);//这个一定要有,如果没有就不知道修改哪个对象 //int update = // sqlSession.update("com.wyxdu.mapper.MonsterMapper.updateMonster", monster); //System.out.println("update--" + update); //查询 List<Monster> monsters = sqlSession.selectList("com.wyxdu.mapper.MonsterMapper.findAllMonster"); for (Monster monster : monsters) { System.out.println("monster--" + monster); } //如果是增删改, 需要提交事务 if(sqlSession != null) { sqlSession.commit(); sqlSession.close(); } System.out.println("操作成功..."); } }
🥰MyBatis-注解的方式操作
在前面项目的基础上,将增删改查,使用 MyBatis 的注解的方式完
1.增加 2.删除
3.修改 4.查询
创建MonsterAnnotation类
package com.wyxedu.mapper; import com.wyxedu.entity.Monster; import org.apache.ibatis.annotations.*; import java.util.List; /** * MonsterAnnotation: 使用注解的方式来配置接口方法 */ public interface MonsterAnnotation { //添加monster /* 解读 1. 使用注解方式配置接口方法addMonster 2. 回顾xml如何配置 <insert id="addMonster" parameterType="Monster" useGeneratedKeys="true" keyProperty="id"> INSERT INTO `monster` (`age`, `birthday`, `email`, `gender`, `name`, `salary`) VALUES (#{age}, #{birthday}, #{email}, #{gender}, #{name}, #{salary}) </insert> 解读 1. useGeneratedKeys = true 返回自增的值 2. keyProperty = "id" 自增值对应的对象属性 3. keyColumn = "id" 自增值对应的表的字段 */ @Insert("INSERT INTO `monster` (`age`, `birthday`, `email`, `gender`, `name`, `salary`) " + "VALUES (#{age}, #{birthday}, #{email}, #{gender}, #{name}, #{salary})") @Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id") public void addMonster(Monster monster); //根据id删除一个Monster /* xml文件中的配置 <delete id="delMonster" parameterType="Integer"> DELETE FROM `monster` WHERE id = #{id} </delete> */ @Delete("DELETE FROM `monster` WHERE id = #{id}") public void delMonster(Integer id); //修改Monster /* <update id="updateMonster" parameterType="Monster"> UPDATE `monster` SET `age`=#{age} , `birthday`= #{birthday}, `email` = #{email}, `gender` = #{gender} , `name`= #{name}, `salary` = #{salary} WHERE id = #{id} </update> */ @Update("UPDATE `monster` " + "SET `age`=#{age} , `birthday`= #{birthday}, `email` = #{email}, " + "`gender` = #{gender} , `name`= #{name}, `salary` = #{salary} " + "WHERE id = #{id}") public void updateMonster(Monster monster); //查询-根据id /* xml配置 <select id="getMonsterById" resultType="Monster"> SELECT * FROM `monster` WHERE id = #{id} </select> */ @Select("SELECT * FROM `monster` WHERE id = #{id}") public Monster getMonsterById(Integer id); //查询所有的Monster /* xml配置 <select id="findAllMonster" resultType="Monster"> SELECT * FROM `monster` </select> */ @Select("SELECT * FROM `monster`") public List<Monster> findAllMonster(); }
修改 mybatis-config.xml , 对 MonsterAnnotaion 进行注册
<mappers> <mapper resource="com/wyxedu/mapper/MonsterMapper.xml"/> <!--解读 1. 如果是通过注解的方式,可不再使用 MonsterMapper.xml 2. 但是需要在mybatis-config.xml注册/引入含注解的类 3. 如果没有引入,不能使用 --> <mapper class="com.wyxedu.mapper.MonsterAnnotation"/> </mappers>
创建MonsterAnnotationTest完成测试
package com.wyxedu.mapper; import com.wyxedu.entity.Monster; import com.wyxedu.util.MyBatisUtils; import org.apache.ibatis.session.SqlSession; import org.junit.Before; import org.junit.Test; import java.util.Date; import java.util.List; public class MonsterAnnotationTest { //属性 private SqlSession sqlSession; private MonsterAnnotation monsterAnnotation; @Before public void init() { //获取到sqlSession sqlSession = MyBatisUtils.getSqlSession(); monsterAnnotation = sqlSession.getMapper(MonsterAnnotation.class); //返回的依然是一个接口的代理对象 System.out.println("monsterAnnotation--" + monsterAnnotation.getClass()); } @Test public void addMonster() { Monster monster = new Monster(); monster.setAge(30); monster.setBirthday(new Date()); monster.setEmail("kate6@qq.com"); monster.setGender(1); monster.setName("狐狸精-100"); monster.setSalary(1000); //使用在接口方法配置注解方式完成对DB操作 monsterAnnotation.addMonster(monster); System.out.println("添加后monster-id-" + monster.getId()); //如果是增删改, 需要提交事务 if(sqlSession != null) { sqlSession.commit(); sqlSession.close(); } System.out.println("保存成功..."); } @Test public void findAllMonster() { //使用接口配置注解的方式操作DB List<Monster> allMonster = monsterAnnotation.findAllMonster(); for (Monster monster : allMonster) { System.out.println("monster--" + monster); } if(sqlSession != null) { sqlSession.close(); } System.out.println("查询成功..."); } }
注意事项和说明
1.如果是通过注解的方式,就不再使用MonsterMapper.xml文件,但是需要在mybatis-config.xml文件中注册含注解的类/接口
2.使用注解方式,添加时,如果要返回自增长id值,可以使用@Option注解
@Insert("INSERT INTO `monster` (`age`, `birthday`, `email`, `gender`, `name`, `salary`) " + "VALUES (#{age}, #{birthday}, #{email}, #{gender}, #{name}, #{salary})") @Options(useGeneratedKeys = true, keyProperty = "id", keyColumn = "id") public void addMonster(Monster monster);
其他的类似
😄总结
通过本教程的学习,我们不仅深入理解了MyBatis原生API和注解方式的运用,更掌握了它们在实现CRUD操作时的优势和便利性。我们学习了如何通过注解简化代码和SQL语句的编写,使其更易于维护和理解。同时,我们也理解了如何有效地测试和验证我们的配置和实现,确保它们的正确性和稳定性
文章到这里就结束了,如果有什么疑问的地方请指出,诸佬们一起来评论区一起讨论😁 希望能和诸佬们一起努力,今后我们一起观看感谢您的阅读🍻 如果帮助到您不妨3连支持一下,创造不易您们的支持是我的动力🤞