当前位置: 首页 > news >正文

MyBatis框架与参数详解

MyBatis框架

  • MyBatis框架概述
  • MyBatis案例与详解

MyBatis框架概述

MyBatis 是一款基于 Java 语言的半自动化对象关系映射(ORM)持久层框架,其核心目标是对 JDBC API 进行抽象与封装,在保留开发者对 SQL 语句精细控制能力的前提下,它有效解决了传统 JDBC 开发中存在的流程冗余、业务逻辑与数据访问逻辑耦合、数据与对象映射复杂等问题。该框架最初由 Apache 软件基金会以“iBatis”为名开源,2010 年迁移至 Google Code 平台并正式更名为“MyBatis”,目前由 GitHub 社区主导维护,是 Java 生态中应用最广泛的持久层框架之一。

MyBatis 可通过 XML 或注解等主流方式,对需执行的 SQL 语句及对应的执行规则进行配置。框架会将 Java 对象中的数据与 SQL 语句中的动态参数进行绑定,进而执行 SQL 操作,SQL 执行完成后,MyBatis 会自动将数据库返回的结果集映射为 Java 对象并返回。

持久层是软件架构中负责数据持久化的核心层级,主要功能是将内存中的临时数据持久化到存储介质(如数据库),并能从存储介质中恢复数据至内存。作为连接业务逻辑层与数据存储层的桥梁,它可避免业务逻辑层直接与数据库交互导致的系统耦合度升高问题。

MyBatis案例与详解

创建数据库和表结构

create database mybatis_db;
use mybatis_db;CREATE TABLE `user` (`id` int(11) NOT NULL auto_increment,`username` varchar(32) NOT NULL COMMENT '用户名称',`birthday` datetime default NULL COMMENT '生日',`sex` char(1) default NULL COMMENT '性别',`address` varchar(256) default NULL COMMENT '地址',PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;insert  into `user`(`id`,`username`,`birthday`,`sex`,`address`) values (1,'老、王','2018-02-27 17:47:08','男','北京'),(2,'熊大','2018-03-02 15:09:37','女','上海'),(3,'熊二','2018-03-04 11:34:34','女','深圳'),(4,'光头强','2018-03-04 12:04:06','男','广州');

创建 maven Java工程
引入坐标依赖,MyBatis的3.4.5的版本坐标,MySQL驱动的jar包5.1.6版本,Junit单元测试的jar包,引入log4j的jar包1.2.12版本(需要引入log4j.properties的配置文件)

    <dependencies><!--mybatis核心包--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.4.5</version></dependency><!--mysql驱动包--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.6</version></dependency><!-- 单元测试 --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.10</version><scope>test</scope></dependency><!-- 日志 --><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency></dependencies>

log4j.properties配置文件
在这里插入图片描述

编写User的实现类,属性尽量使用包装类型

import java.io.Serializable;
import java.util.Date;public class User implements Serializable {private Integer id;private String username;private Date birthday;private String sex;private String address;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + username + '\'' +", birthday=" + birthday +", sex='" + sex + '\'' +", address='" + address + '\'' +'}';}
}

编写UserMapper的接口和方法

import java.util.List;public interface UserMapper {//查询所有的用户public List<User> findAll();}

在resources目录下,创建mapper文件夹,编写UserMapper.xml配置文件,导入约束文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.qcby.mapper.UserMapper"><select id="findAll" resultType="com.qcby.domain.User">select * from user;</select></mapper>

通过namespace关联com.qcby.mapper.UserMapper接口,为接口中的findAll()方法绑定一条SQL语句,并指定查询结果会被映射为User对象。

编写主配置文件,在resources目录下创建SqlMapConfig.xml配置文件,导入对应的约束,编写主配置文件。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><environments default="mysql"><environment id="mysql"><!-- 配置事务管理类型 --><transactionManager type="JDBC"/><!-- 配置是否需要使用连接池,POOLED使用,UNPOOLED不使用 --><dataSource type="POOLED"><property name="driver" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql:///mybatis_db"/><property name="username" value="root"/><property name="password" value="root"/></dataSource></environment></environments><!-- 加载映射的配置文件 --><mappers><mapper resource="mappers/UserMapper.xml"/></mappers>
</configuration>

编写测试代码

import com.qcby.domain.User;
import com.qcby.mapper.UserMapper;
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 org.junit.Test;import java.io.InputStream;
import java.util.List;public class UserTest {/*** 测试查询所有的方法* @throws Exception*/@Testpublic void testFindAll() throws Exception {InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);SqlSession session = factory.openSession();UserMapper mapper = session.getMapper(UserMapper.class);List<User> list = mapper.findAll();for (User user : list) {System.out.println(user);}session.close();in.close();}@Testpublic void run() throws Exception {InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);SqlSession session = factory.openSession();List<User> list = session.selectList("com.qcby.mapper.UserMapper.findAll");for (User user : list) {System.out.println(user);}session.close();inputStream.close();}
}

实现效果:

执行testFindAll()

在这里插入图片描述

testFindAll () 函数通过 MyBatis 的接口代理方式实现数据库查询
首先利用 MyBatis 的 Resources 工具类加载主配置文件 SqlMapConfig.xml 的输入流,再通过 SqlSessionFactoryBuilder 构建出 SqlSessionFactory 会话工厂,随后打开 SqlSession 会话,调用 SqlSession 的 getMapper (UserMapper.class) 获取 UserMapper 接口的代理对象,调用代理对象的 findAll () 方法时,MyBatis 会自动匹配 UserMapper.xml 中对应 namespace 和 id 的 SQL 语句执行查询,得到 User 对象集合并打印,最后释放资源。这种方式面向接口编程,支持编译期类型检查,是 MyBatis 官方推荐的规范用法。

执行run()

在这里插入图片描述

run () 函数采用 MyBatis 传统的命名空间 + ID 方式执行查询
流程上同样先加载配置文件、创建 SqlSessionFactory 并打开 SqlSession,但执行查询时直接调用 SqlSession 的 selectList () 方法,通过字符串 “com.qcby.mapper.UserMapper.findAll” 定位目标 SQL,得到 User 对象集合并打印,最后释放资源。

实现增删改查
UserMapper接口代码

import com.qcby.domain.User;import java.util.List;public interface UserMapper {public List<User> findAll();public User findById(Integer userId);public void insert(User user);public void update(User user);public void delete(Integer userId);public List<User> findByName1(String username);public List<User> findByName2(String username);public Integer findByCount();}

UserMapper.xml的配置文件代码

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.qcby.mapper.UserMapper"><select id="findAll" resultType="com.qcby.domain.User">select * from user;</select><!-- 通过id查询,SQL语句使用#{}占位符的名称,名称可以任意,仅限于基本数据类型和String类型--><select id="findById" resultType="com.qcby.domain.User" parameterType="int">select * from user where id = #{id};</select><!--保存操作--><insert id="insert" parameterType="com.qcby.domain.User"><selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">select last_insert_id();</selectKey>insert into user (username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address})</insert><!-- 修改 --><update id="update" parameterType="com.qcby.domain.User">update user set username = #{username},birthday = #{birthday},sex = #{sex},address=#{address} where id = #{id}</update><!-- 删除 --><delete id="delete" parameterType="Integer">delete from user where id = #{id}</delete><!-- 模糊查询1 --><select id="findByName1" resultType="com.qcby.domain.User" parameterType="string">select * from user where username  like #{username}</select><!-- 模糊查询2,固定写法 --><select id="findByName2" resultType="com.qcby.domain.User" parameterType="string">select * from user where username  like '%${value}%'</select><!-- 具体函数的查询 --><select id="findByCount" resultType="int">select count(*) from user</select>
</mapper>

UserTest 代码

package com.qcby;import com.qcby.domain.User;
import com.qcby.mapper.UserMapper;
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 org.junit.After;
import org.junit.Before;
import org.junit.Test;import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;public class UserTest1 {private InputStream in;private SqlSession session;private UserMapper mapper;@Beforepublic void init() throws Exception {in = Resources.getResourceAsStream("SqlMapConfig.xml");SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);session = factory.openSession();mapper = session.getMapper(UserMapper.class);}@Afterpublic void destory() throws IOException {in.close();session.close();}@Testpublic void testFindAll() throws Exception {List<User> list = mapper.findAll();// 遍历for (User user : list) {System.out.println(user);}in.close();}@Testpublic void testFindById() throws Exception {User user = mapper.findById(41);System.out.println(user);in.close();}@Testpublic void testInsert() throws Exception {User user = new User();user.setUsername("美美");user.setBirthday(new Date());user.setSex("男");user.setAddress("顺义");mapper.insert(user);session.commit();System.out.println(user.getId());}@Testpublic void testUpdate() throws Exception {User user = mapper.findById(4);user.setUsername("小凤");mapper.update(user);session.commit();}@Testpublic void testDelete() throws Exception {mapper.delete(2);session.commit();}// 第一种@Testpublic void testFindByName() throws Exception {List<User> list = mapper.findByName1("%王%");for (User user : list) {System.out.println(user);}}// 第二种@Testpublic void testFindByName1() throws Exception {List<User> list = mapper.findByName2("王");for (User user : list) {System.out.println(user);}}@Testpublic void testFindByCount() throws Exception {Integer count = mapper.findByCount();System.out.println("总记录数:"+count);}
}

实现效果:

执行 testInsert() 方法

在这里插入图片描述

该方法执行的是这条SQL语句

	<insert id="insert" parameterType="com.qcby.domain.User"><selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer">select last_insert_id();</selectKey>insert into user (username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address})</insert>

其中selectKey标签用于获取插入记录后自动生成的主键值,keyProperty=“id” 表示将查询到的主键值赋值给传入User对象的id属性,order=“AFTER” 指定该查询在insert语句执行之后执行(自增长主键是在记录插入后生成的),resultType=“java.lang.Integer” 声明查询返回的主键类型为Integer,内部 SQL select last_insert_id(); 是 MySQL 的内置函数,用于获取当前会话中最后一次插入操作生成的自增长主键值。MyBatis 通过 <selectKey> 获取到主键值后,会主动调用对象的setId()方法赋值,而由于对象是引用传递,外部的user对象就能通过getId()获取到这个值。

session.commit() 的核心功能是提交事务,确保数据库修改持久化。在 MyBatis 中,默认采用 JDBC 事务管理机制(对应配置中的 <transactionManager type="JDBC"/>),通过 factory.openSession() 获取的 SqlSession 默认开启事务且不自动提交。当执行 mapper.insert(user) 时,插入操作仅暂存于事务中,直到调用 session.commit() 才会将数据永久写入数据库,完成数据持久化,若未显式调用 commit(),SqlSession 关闭时会自动执行事务回滚,所有未提交的修改都将被撤销,数据库不会保留新增数据。

模糊查询符号使用的区别

  • #{} 本质是MyBatis对JDBC中PreparedStatement占位符机制的封装,会被解析为SQL中的 ?,后续通过PreparedStatement的setXxx()方法将参数值安全传入。它具备自动类型转换能力,可根据Java参数类型(如String、Integer)与数据库字段的JDBC类型(如VARCHAR、INT)完成适配,无需手动处理兼容问题。同时,因参数以纯数据形式通过预编译占位符传入,特殊字符会被转义,能有效抵御SQL注入攻击。在参数接收上,#{}可处理简单类型值(如int、String)与POJO对象的属性值,当parameterType为单个简单类型时,其括号内的名称可任意填写,MyBatis均能正确识别。
  • ${} 采用直接字符串替换的处理逻辑,不会生成SQL占位符,而是将参数值直接拼接至SQL语句中,且不进行任何JDBC类型转换,无论Java参数是int型还是String型,最终都会以字符串形式拼入。它同样支持接收简单类型值与POJO属性值,但在参数规则上与#{}存在差异:当parameterType为单个简单类型时,${}括号内必须填写“value”,否则MyBatis无法识别对应参数,这是其与#{}在单个简单类型参数处理上的核心区别。

实现效果:

在这里插入图片描述
在这里插入图片描述

MyBatis参数详解

  • parameterType
    parameterType 是 MyBatis 中用于指定 SQL 语句接收参数类型的配置属性。它主要作用是告诉 MyBatis 传入 SQL 的参数数据类型,以便框架正确解析和处理参数。该属性的值可以是基本数据类型(如 int、String)、包装类(如 Integer、Long)、自定义实体类、Map 等集合类型。在 Mapper 接口方法中,当参数为单个简单类型时,parameterType的取值可以是Java 类型的全限定名(如java.lang.Integer),也可以是 MyBatis 内置的类型别名(如int);但对于复杂类型(如自定义对象),parameterType需指定该类的全限定名或自定义别名。
  • resultType
    resultType 用于指定 SQL 查询语句返回结果的类型,它告诉 MyBatis查询结果需要被映射成什么类型的对象,MyBatis 会根据该类型,将 SQL 执行后的结果集自动封装为对应的对象或数据结构,它适用于结果集字段与 Java 对象属性名完全一致的场景。MyBatis 会根据 resultType 定义的类型,自动将查询结果集中的列值映射到对应类型的对象属性中。其取值可以是基本数据类型(如 String、int)、自定义实体类、List 等集合类型(此时需指定集合中元素的类型)。
  • resultMap
    resultMap 是 MyBatis 中用于自定义结果映射规则的配置标签,适用于结果集字段与 Java 对象属性名不一致,或存在复杂关联关系(如一对一、一对多)的场景。它通过(主键映射)和(普通字段映射)标签,手动指定数据库列名与 Java 对象属性名的对应关系,解决字段名与属性名不匹配的问题。此外,resultMap 还支持通过(一对一关联)和(一对多关联)标签处理关联查询,实现复杂对象的嵌套映射。与 resultType 相比,resultMap 的优势在于灵活性和可复用性,一旦定义可在多个 SQL 语句中引用,尤其适合处理复杂的数据映射场景。

类型别名定义
MyBatis 内置了一些常用类型的别名(如int对应Integer、string对应String、list对应ArrayList等),开发者无需手动定义即可直接使用。
也可以进行别名的注册,在SqlMapConfig.xml配置文件中设置

<!-- 定义别名 -->
<typeAliases><!-- 把com.qcby.domain.User使用user别名来显示<typeAlias type="com.qcby.domain.User" alias="user"/>--><!-- 针对com.qcby.domain包下的所有的类,都可以使用当前的类名做为别名 --><package name="com.qcby.domain"/>
</typeAliases>

在 MyBatis 的核心配置文件中,使用<typeAlias>标签单独指定某个类的别名,或通过<package>标签批量扫描某个包下的所有类,此时 MyBatis 会默认以类名(首字母大小写均可,不区分大小写)作为别名,例如扫描com.qcby.domain包后,User类可直接用user或User作为别名

<select id="findAll" resultType="user">select * from user
</select>

定义后的类型别名可直接在 Mapper 配置文件的parameterType、resultType等属性中使用,其值不再是原来的全路径了

http://www.dtcms.com/a/391368.html

相关文章:

  • Confluent-Kafka-go 发布超过 1M 消息失败问题解决
  • 数字图像处理-函数矩阵
  • 基于 ST-Link 和 MDK-Keil 的 STM32 程序下载实验
  • 安防监控系统的架构与组成原理
  • 【前端】【threeJs】前端事件偏移问题完整总结
  • web:ts的类型兼容性
  • 黑盒测试:测试用例设计之场景法(流程图法)(模拟用户实际使用软件的场景来设计测试用例,适用于业务流程复杂的系统测试)基本流、备选流
  • Django + Vue3 前后端分离技术实现自动化测试平台从零到有系列 <第二章> 之 平台功能架构整理
  • 神经网络学习笔记14——高效卷积神经网络架构EfficientNet
  • Flutter实现滑动页面停留吸附
  • 【Linux】基本指令介绍
  • 爬虫逆向--Day22Day23--核心实战案例【荔枝网】【WASM学习】----待完成
  • 【软考-系统架构设计师】特定领域软件体系结构(DSSA)
  • idea git使用提示问题处理
  • 数据结构初阶——哈希表的实现(C++)
  • Problem: lab-week3- exercise01 Insertion sort
  • 金融级虚拟机安全:虚拟化平台5大安全风险与国产化防护实践
  • 可视化在智慧城市中的应用
  • C#实现高性能拍照(旋转)与水印添加功能完整指南
  • Pandas 2.x与PyArrow:深入探索内存优化与性能提升技巧
  • opencv之轮廓识别
  • lesson65:JavaScript字符串操作完全指南:从基础到高级实战
  • 【脑电分析系列】第19篇:深度学习方法(一):卷积神经网络(CNN)在EEG图像/时频图分类中的应用
  • 写文件的几种方法
  • 序列化与反序列化漏洞及防御详解
  • uniapp 锁定竖屏,固定竖屏,锁定屏幕
  • 论文解读 | Franka 机器人的 CRISP-ROS2 集成实践:适配学习型操作策略与遥操作
  • Redis数据库(二)—— Redis 性能管理与缓存问题解决方案指南
  • TCP KeepAlive判断离线的记录
  • Ceph 测试环境 PG_BACKFILL_FULL