Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。
那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议,那么话不多说直接上教程👏👏👏!!!
目录
正向工程 与 逆向工程
1、什么是Mybatis逆向工程
MyBatis 逆向工程使用注意事项
2、逆向工程生成代码
①、首先创建maven项目
②、创建日志文件log4j.properties
③、创建generatorConfig.xml配置文件
④、创建逆向工程核心生成代码GeneratorSql.java
⑤、运行逆向工程生成代码
3、逆向工程举例
(1)、EmpMapper接口生成的方法介绍:
测试不带条件的方法:
(2)、EmpExample条件扩展类介绍:
说明:
简单举例:
正向工程 与 逆向工程
-
正向工程:先创建Java实体类,由框架负责根据实体类生成数据表。Hibernate 是支持正向工程的。
-
逆向工程:先创建数据库表,由框架负责根据数据库表,反向生成Java实体类、Mapper接口、Mapper配置文件
1、什么是Mybatis逆向工程
MyBatis逆向工程是一种自动化生成代码的工具,它能够根据数据库表结构自动创建对应的Java实体类、Mapper接口以及Mapper映射文件。
在MyBatis开发中,我们通常需要手动编写实体类、Mapper接口和XML映射文件,尤其是当数据库表较多或字段复杂时,这种重复性工作不仅效率低下,还容易因人为疏忽导致错误。例如,字段类型不匹配、遗漏字段或拼写错误等问题,排查起来相当耗时。
为了解决这一问题,MyBatis逆向工程应运而生。它通过扫描数据库表结构,自动生成标准化的基础代码,极大地减少了开发者的手动编码量,尤其适用于单表CRUD操作。这不仅提升了开发效率,也降低了出错概率,让开发者能更专注于业务逻辑的实现。
MyBatis 逆向工程使用注意事项
1. 避免直接在原项目中使用逆向工程
-
风险: 逆向工程生成的代码(如
User.java
、UserMapper.java
、UserMapper.xml
)可能会覆盖原有文件,导致手动编写的业务逻辑丢失。 -
解决方案:
-
新建一个临时项目,专门用于运行逆向工程生成代码。
-
生成后,手动复制所需文件到目标项目,避免直接覆盖。
-
2. 生成代码后需检查调整
-
自定义逻辑可能被覆盖:生成的
Mapper.xml
文件会包含基本的 CRUD 方法,如果原文件已有自定义 SQL(如复杂查询、关联查询),直接覆盖会导致功能失效。 -
建议:
-
仅复制新增的实体类或 Mapper 接口,避免覆盖已有业务代码。
-
使用
@Mapper
扫描 + 自定义 XML 的方式,分离自动生成代码和手动编写代码。
-
3.版本管理(Git)备份:在运行逆向工程前,确保代码已提交到 Git,避免意外覆盖导致不可逆的损失。
2、逆向工程生成代码
①、首先创建maven项目
项目整体目录:
导入maven依赖:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion>
<!--组织名称--><groupId>com.nanji</groupId><!--项目唯一标识--><artifactId>GeneratorSql</artifactId><!--版本号--><version>1.0</version><!--打包方式--><packaging>jar</packaging>
<!--项目名称(显示用)--><name>GeneratorSql</name><!--项目的url地址--><url>https://maven.apache.org</url>
<!--声明可在pom文件中可以使用的键值对变量(用:${}引用)例如:${poject.build.sourceEncoding},值:UTF-8--><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties>
<!--以来列表容器,用来存放依赖的jar包--><dependencies><!--dependency:依赖项groupId:依赖项的组IDartifactId:依赖项的IDversion:依赖项的版本-->
<!--mybatis jar包--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.11</version></dependency>
<!--mysql驱动 jar包--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version></dependency>
<!--log4j日志 jar包--><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency></dependencies>
<!-- 控制Maven在构建过程中相关配置 --><build><!-- 构建过程中用到的插件 --><plugins><!--plugin:具体插件,逆向工程的操作是以构建过程中插件形式出现的groupId:插件的组IDartifactId:插件的ID--><plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>1.4.0</version><!-- 插件的依赖列表容器 --><dependencies><!-- 逆向工程的核心依赖 --><dependency><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-core</artifactId><version>1.4.0</version></dependency><!-- 数据库连接池 --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.24</version></dependency>
<!-- MySQL驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version></dependency></dependencies></plugin></plugins></build>
</project>
②、创建日志文件log4j.properties
# 配置日志输出到控制台(STDOUT)
log4j.appender.STDOUT=org.apache.log4j.ConsoleAppender
log4j.appender.STDOUT.Encoding=UTF-8
log4j.appender.STDOUT.layout=org.apache.log4j.PatternLayout
log4j.appender.STDOUT.layout.ConversionPattern=%-5p %d{MM-dd HH:mm:ss,SSS} %m (%F:%L) \n
# 设置 java.sql 的日志级别为 debug
log4j.logger.java.sql=debug
# 设置 org.apache.ibatis 的日志级别为 info
log4j.logger.org.apache.ibatis=info
# 配置根日志记录器,日志级别为 debug,输出到 STDOUT
log4j.rootLogger=debug, STDOUT
③、创建generatorConfig.xml配置文件
文件名必须是 generatorConfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN""http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration><!-- targetRuntime: 执行生成的逆向工程的版本MyBatis3Simple: 生成基本的CRUD(清新简洁版)MyBatis3: 生成带条件的CRUD(奢华尊享版) --><context id="DB2Tables" targetRuntime="MyBatis3"><!--TODO 配置自己的数据库连接信息:驱动类、连接地址、用户名、密码连接地址中的 & 实际上就是 & 符号的转义字符,由于 xml 文件中直接写 & 时,xml 解析器会认为 & 后面的是实体,从而报错--><jdbcConnectiondriverClass="com.mysql.cj.jdbc.Driver"connectionURL="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai"userId="nanji"password="123456"></jdbcConnection><!--默认false:把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为true时:把JDBC DECIMAL 和 NUMERIC 类型解析为 java.math.BigDecimal--><javaTypeResolver><property name="forceBigDecimals" value="false"/></javaTypeResolver><!--javaBean的生成策略targetProject:POJO类生成的位置--><javaModelGenerator targetPackage="com.nanji.mybatis.pojo" targetProject=".\src\main\java"><!-- enableSubPackages:是否让schema作为包的后缀 --><property name="enableSubPackages" value="true"/><!-- 从数据库返回的值被清理前后的空格 --><property name="trimStrings" value="true"/></javaModelGenerator><!--SQL映射文件的生成策略targetProject:mapper映射文件生成的位置--><sqlMapGenerator targetPackage="com.nanji.mybatis.mapper" targetProject=".\src\main\resources"><!-- enableSubPackages:是否让schema作为包的后缀 --><property name="enableSubPackages" value="true"/></sqlMapGenerator><!--Mapper接口的生成策略targetPackage:mapper接口生成的位置--><javaClientGenerator type="XMLMAPPER" targetPackage="com.nanji.mybatis.mapper"targetProject=".\src\main\java"><!-- enableSubPackages:是否让schema作为包的后缀 --><property name="enableSubPackages" value="true"/></javaClientGenerator><!-- 逆向分析的表 --><!-- tableName设置为*号,可以对应所有表,此时不写domainObjectName --><!-- domainObjectName属性指定生成出来的实体类的类名 --><table tableName="t_emp" domainObjectName="Emp"><!--property:实体类属性名columnOverride:对数据库字段的设置column:数据库字段名javaType:实体类属性的数据类型--><!--<property column="" javaType=""/>--></table><table tableName="t_dept" domainObjectName="Dept"/></context>
</generatorConfiguration>
注意:数据库连接地址中的 & 实际上就是 & 符号的转义字符,由于 xml 文件中直接写 & 时,xml 解析器会认为 & 后面的是实体,从而报错
<jdbcConnectiondriverClass="com.mysql.cj.jdbc.Driver"connectionURL="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai"userId="nanji"password="123456">
</jdbcConnection>
还有就是不同的数据库中不能含有相同的表,例如数据库A有t_user表,数据库B也有t_user表,那么到时候代码不知道生成哪个
④、创建逆向工程核心生成代码GeneratorSql.java
package com.nanji;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/*** @version 1.0* @ClassName GeneratorSql* @Description 逆向工程生成代码的核心类* @Author NanJi* @Date 2025/6/10 : 16:01*/
public class GeneratorSql {// 执行main方法以生成代码public static void main(String[] args) {try {GeneratorSql generatorSql = new GeneratorSql();generatorSql.generator();} catch (Exception e) {e.printStackTrace();}}
public void generator() throws Exception {List<String> warnings = new ArrayList<>();boolean overwrite = true;// 指定逆向工程配置文件String file = GeneratorSql.class.getResource("/generatorConfig.xml").getFile();System.out.println(file);File configFile = new File(file);ConfigurationParser cp = new ConfigurationParser(warnings);Configuration config = cp.parseConfiguration(configFile);DefaultShellCallback callback = new DefaultShellCallback(overwrite);MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);myBatisGenerator.generate(null);}
}
⑤、运行逆向工程生成代码
运行上面的程序,如果控制台打印了如下日志,说明生成代码成功了。
或者
使用maven插件进行代码生成
如果控制台打印了如下日志,说明生成代码成功了。
然后我们的项目结构会发生变化,生成了如下文件:
3、逆向工程举例
首先我们将上面生成的文件复制到目标项目中。在使用逆向工程举例之前,先来介绍生成的文件有哪些东西:
(1)、EmpMapper接口生成的方法介绍:
方法 | 说明 |
---|---|
long countByExample(EmpExample example); | 按条件计数 |
int deleteByExample(EmpExample example); | 按条件删除 |
int deleteByPrimaryKey(Integer empid); | 按主键删除 |
int insert(Emp record); | 插入数据(返回值为ID) |
int insertSelective(Emp record); | 插入数据,只插入值不为null的字段,内部动态sql判断 |
List<Emp> selectByExample(EmpExample example); | 按条件查询,传入null表示查询所有 |
Emp selectByPrimaryKey(Integer empid); | 按主键查询 |
int updateByExampleSelective(@Param("record") Emp record, @Param("example") EmpExample example); | 按条件更新值不为null的字段 |
int updateByExample(@Param("record") Emp record, @Param("example") EmpExample example); | 按条件更新 |
int updateByPrimaryKeySelective(Emp record); | 按主键更新值不为null的字段 |
int updateByPrimaryKey(Emp record); | 按主键更新 |
测试不带条件的方法:
package com.nanji.mybatis.mapper;
import com.nanji.mybatis.pojo.Emp;
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.List;
public class EmpMapperTest {//定义 SqlSessionprivate SqlSession sqlSession = null;//定义 EmpMapper对象private EmpMapper mapper = null;
@Before//在测试方法执行之前执行public void getSqlSession() {//1、加载 mybatis 全局配置文件InputStream is = EmpMapperTest.class.getClassLoader().getResourceAsStream("mybatis-config.xml");//2、创建SqlSessionFactory对象SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);//3、根据 sqlSessionFactory 产生sessionsqlSession = sqlSessionFactory.openSession();//4、创建Mapper接口的的代理对象,getMapper方法底层会通过动态代理生成EmpMapper的代理实现类mapper = sqlSession.getMapper(EmpMapper.class);}
@After//在测试方法执行完成之后执行public void destroy() throws IOException {sqlSession.commit();sqlSession.close();}
//查询所有用户信息@Testpublic void selectAllUser() {List<Emp> Emps = mapper.selectByExample(null);//传入null表示查询所有for (Emp Emp : Emps) {System.out.println(Emp);}}
//根据用户id查询用户@Testpublic void selectByUserId() {Emp Emp = mapper.selectByPrimaryKey(1);System.out.println(Emp);}
//添加用户信息@Testpublic void inserEmp() {Emp Emp = new Emp();Emp.setEmpName("凡尔赛");Emp.setAge(18);Emp.setSex("男");Emp.setEmail("piaoliang@gmail.com");Emp.setDeptid(1);int i = mapper.insertSelective(Emp);System.out.println(i > 0 ? "添加成功" : "添加失败");}
//更新用户信息@Testpublic void updateUser() {Emp Emp = new Emp();Emp.setEmpid(15); //这里要设置id才能修改成功,否则不知道修改哪一条数据Emp.setEmpName("奥德赛");Emp.setAge(18);Emp.setSex("男");Emp.setEmail("aodesai@gmail.com");Emp.setDeptid(1);int i = mapper.updateByPrimaryKeySelective(Emp);System.out.println(i > 0 ? "修改成功" : "修改失败");}
//删除用户信息@Testpublic void deleteUser() {int i = mapper.deleteByPrimaryKey(8);System.out.println(i > 0 ? "删除成功" : "删除失败");}
}
(2)、EmpExample条件扩展类介绍:
上面的测试方法是不带条件的操作,那么接下来学习一下按条件如何进行增删改查操作,我们在逆向工程中已经生成了这个类EmpExample,这个类就是一个条件扩展类,里面定义了一系列方法用来做条件,比如:排序、去重、大于、小于、等于、模糊查询、数据在某某之间等等。
我们在EmpExample类中可以看到定义了一个内部类GeneratedCriteria,这个内部类就定义了一系列条件的方法,这些条件最后都会拼接在SQL中,但是我们一般不用它,都用它的子类Criteria来进行操作,Criteria继承了内部类GeneratedCriteria。
方法 | 说明 |
---|---|
isValid() | 判断当前查询条件列表是否非空,即是否有有效的查询条件 |
getAllCriteria() | 获取所有的查询条件(Criterion 对象列表) |
getCriteria() | 获取当前查询条件列表 |
addCriterion(String condition) | 添加一个无参数的查询条件(如 "empId is null" ) |
addCriterion(String condition, Object value, String property) | 添加一个带单个值的查询条件,并校验值是否为空 |
addCriterion(String condition, Object value1, Object value2, String property) | 添加一个区间类型的查询条件(如 BETWEEN),并校验两个值是否都非空 |
andEmpidIsNull() | 添加 empId IS NULL 查询条件 |
andEmpidIsNotNull() | 添加 empId IS NOT NULL 查询条件 |
andEmpidEqualTo(Integer value) | 添加 empId = value 查询条件 |
andEmpidNotEqualTo(Integer value) | 添加 empId <> value 查询条件 |
andEmpidGreaterThan(Integer value) | 添加 empId > value 查询条件 |
andEmpidGreaterThanOrEqualTo(Integer value) | 添加 empId >= value 查询条件 |
andEmpidLessThan(Integer value) | 添加 empId < value 查询条件 |
andEmpidLessThanOrEqualTo(Integer value) | 添加 empId <= value 查询条件 |
andEmpidIn(List<Integer> values) | 添加 empId IN (values) 查询条件 |
andEmpidNotIn(List<Integer> values) | 添加 empId NOT IN (values) 查询条件 |
andEmpidBetween(Integer value1, Integer value2) | 添加 empId BETWEEN value1 AND value2 查询条件 |
andEmpidNotBetween(Integer value1, Integer value2) | 添加 empId NOT BETWEEN value1 AND value2 查询条件 |
andEmpNameIsNull() | 添加 emp_name IS NULL 查询条件 |
andEmpNameIsNotNull() | 添加 emp_name IS NOT NULL 查询条件 |
andEmpNameEqualTo(String value) | 添加 emp_name = value 查询条件 |
andEmpNameNotEqualTo(String value) | 添加 emp_name <> value 查询条件 |
andEmpNameGreaterThan(String value) | 添加 emp_name > value 查询条件 |
andEmpNameGreaterThanOrEqualTo(String value) | 添加 emp_name >= value 查询条件 |
andEmpNameLessThan(String value) | 添加 emp_name < value 查询条件 |
andEmpNameLessThanOrEqualTo(String value) | 添加 emp_name <= value 查询条件 |
andEmpNameLike(String value) | 添加 emp_name LIKE value 查询条件 |
andEmpNameNotLike(String value) | 添加 emp_name NOT LIKE value 查询条件 |
andEmpNameIn(List<String> values) | 添加 emp_name IN (values) 查询条件 |
andEmpNameNotIn(List<String> values) | 添加 emp_name NOT IN (values) 查询条件 |
andEmpNameBetween(String value1, String value2) | 添加 emp_name BETWEEN value1 AND value2 查询条件 |
andEmpNameNotBetween(String value1, String value2) | 添加 emp_name NOT BETWEEN value1 AND value2 查询条件 |
andAgeIsNull() | 添加 age IS NULL 查询条件 |
andAgeIsNotNull() | 添加 age IS NOT NULL 查询条件 |
andAgeEqualTo(Integer value) | 添加 age = value 查询条件 |
andAgeNotEqualTo(Integer value) | 添加 age <> value 查询条件 |
andAgeGreaterThan(Integer value) | 添加 age > value 查询条件 |
andAgeGreaterThanOrEqualTo(Integer value) | 添加 age >= value 查询条件 |
andAgeLessThan(Integer value) | 添加 age < value 查询条件 |
andAgeLessThanOrEqualTo(Integer value) | 添加 age <= value 查询条件 |
andAgeIn(List<Integer> values) | 添加 age IN (values) 查询条件 |
andAgeNotIn(List<Integer> values) | 添加 age NOT IN (values) 查询条件 |
andAgeBetween(Integer value1, Integer value2) | 添加 age BETWEEN value1 AND value2 查询条件 |
andAgeNotBetween(Integer value1, Integer value2) | 添加 age NOT BETWEEN value1 AND value2 查询条件 |
andSexIsNull() | 添加 sex IS NULL 查询条件 |
andSexIsNotNull() | 添加 sex IS NOT NULL 查询条件 |
andSexEqualTo(String value) | 添加 sex = value 查询条件 |
andSexNotEqualTo(String value) | 添加 sex <> value 查询条件 |
andSexGreaterThan(String value) | 添加 sex > value 查询条件 |
andSexGreaterThanOrEqualTo(String value) | 添加 sex >= value 查询条件 |
andSexLessThan(String value) | 添加 sex < value 查询条件 |
andSexLessThanOrEqualTo(String value) | 添加 sex <= value 查询条件 |
andSexLike(String value) | 添加 sex LIKE value 查询条件 |
andSexNotLike(String value) | 添加 sex NOT LIKE value 查询条件 |
andSexIn(List<String> values) | 添加 sex IN (values) 查询条件 |
andSexNotIn(List<String> values) | 添加 sex NOT IN (values) 查询条件 |
andSexBetween(String value1, String value2) | 添加 sex BETWEEN value1 AND value2 查询条件 |
andSexNotBetween(String value1, String value2) | 添加 sex NOT BETWEEN value1 AND value2 查询条件 |
andEmailIsNull() | 添加 email IS NULL 查询条件 |
andEmailIsNotNull() | 添加 email IS NOT NULL 查询条件 |
andEmailEqualTo(String value) | 添加 email = value 查询条件 |
andEmailNotEqualTo(String value) | 添加 email <> value 查询条件 |
andEmailGreaterThan(String value) | 添加 email > value 查询条件 |
andEmailGreaterThanOrEqualTo(String value) | 添加 email >= value 查询条件 |
andEmailLessThan(String value) | 添加 email < value 查询条件 |
andEmailLessThanOrEqualTo(String value) | 添加 email <= value 查询条件 |
andEmailLike(String value) | 添加 email LIKE value 查询条件 |
andEmailNotLike(String value) | 添加 email NOT LIKE value 查询条件 |
andEmailIn(List<String> values) | 添加 email IN (values) 查询条件 |
andEmailNotIn(List<String> values) | 添加 email NOT IN (values) 查询条件 |
andEmailBetween(String value1, String value2) | 添加 email BETWEEN value1 AND value2 查询条件 |
andEmailNotBetween(String value1, String value2) | 添加 email NOT BETWEEN value1 AND value2 查询条件 |
andDeptidIsNull() | 添加 deptId IS NULL 查询条件 |
andDeptidIsNotNull() | 添加 deptId IS NOT NULL 查询条件 |
andDeptidEqualTo(Integer value) | 添加 deptId = value 查询条件 |
andDeptidNotEqualTo(Integer value) | 添加 deptId <> value 查询条件 |
andDeptidGreaterThan(Integer value) | 添加 deptId > value 查询条件 |
andDeptidGreaterThanOrEqualTo(Integer value) | 添加 deptId >= value 查询条件 |
andDeptidLessThan(Integer value) | 添加 deptId < value 查询条件 |
andDeptidLessThanOrEqualTo(Integer value) | 添加 deptId <= value 查询条件 |
andDeptidIn(List<Integer> values) | 添加 deptId IN (values) 查询条件 |
andDeptidNotIn(List<Integer> values) | 添加 deptId NOT IN (values) 查询条件 |
andDeptidBetween(Integer value1, Integer value2) | 添加 deptId BETWEEN value1 AND value2 查询条件 |
andDeptidNotBetween(Integer value1, Integer value2) | 添加 deptId NOT BETWEEN value1 AND value2 查询条件 |
说明:
-
所有
andXXX
方法均用于构建针对t_emp
表中字段的查询条件。 -
这些方法基于 MyBatis Generator 自动生成,常用于动态 SQL 查询,配合 MyBatis 框架使用。
-
Criteria 继承自 GeneratedCriteria,提供对外使用的 API。
简单举例:
package com.nanji.mybatis.mapper;
import com.nanji.mybatis.pojo.Emp;
import com.nanji.mybatis.pojo.EmpExample;
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.List;
public class EmpMapperExampleTest {
//定义 SqlSessionprivate SqlSession sqlSession = null;//定义 UserMapper对象private EmpMapper mapper = null;
@Before//在测试方法执行之前执行public void getSqlSession() {//1、加载 mybatis 全局配置文件InputStream is = EmpMapperExampleTest.class.getClassLoader().getResourceAsStream("mybatis-config.xml");//2、创建SqlSessionFactory对象SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);//3、根据 sqlSessionFactory 产生sessionsqlSession = sqlSessionFactory.openSession();//4、创建Mapper接口的的代理对象,getMapper方法底层会通过动态代理生成UserMapper的代理实现类mapper = sqlSession.getMapper(EmpMapper.class);}
@After//在测试方法执行完成之后执行public void destroy() throws IOException {sqlSession.commit();sqlSession.close();}
//模糊查询用户信息@Testpublic void selecEmpLike() {EmpExample example = new EmpExample();EmpExample.Criteria criteria = example.createCriteria();//模糊条件criteria.andEmpNameLike("%三%");/*sql语句相当于:select id, username, age, birthday, sex, address from t_user WHERE ( username like ? )*/List<Emp> Emps = mapper.selectByExample(example);for (Emp Emp : Emps) {System.out.println(Emp);}}
//查询年龄在18-30岁之间的用户信息@Testpublic void selecEmpBetween() {EmpExample example = new EmpExample();EmpExample.Criteria criteria = example.createCriteria();//Between条件criteria.andAgeBetween(18, 30);example.or(criteria);example.setDistinct(true);/*sql语句相当于:select distinct id, username, age, birthday, sex, address from t_user WHERE ( age between ? and ? ) or( age between ? and ? )*/List<Emp> Emps = mapper.selectByExample(example);for (Emp Emp : Emps) {System.out.println(Emp);}}
//查询用户名A或B@Testpublic void selecEmpOr() {EmpExample example = new EmpExample();EmpExample.Criteria criteria1 = example.createCriteria();criteria1.andEmpNameEqualTo("黄飞鸿");
EmpExample.Criteria criteria2 = example.createCriteria();criteria2.andEmpNameEqualTo("马保国");//将criteria2条件拼接在 or 关键字字后面example.or(criteria2);/*sql语句相当于:select id, username, age, birthday, sex, addressfrom t_user WHERE ( username = ? ) or( username = ? )*/List<Emp> Emps = mapper.selectByExample(example);for (Emp Emp : Emps) {System.out.println(Emp);}}
//根据用户名删除用户@Testpublic void deleteUserExample() {EmpExample example = new EmpExample();EmpExample.Criteria criteria = example.createCriteria();criteria.andEmpNameEqualTo("凡尔赛");//sql语句相当于:delete from t_user WHERE ( username = ? )int i = mapper.deleteByExample(example);System.out.println(i > 0 ? "删除成功" : "删除失败");}
}
欧了,到这里我应该解释的差不多啦,我是南极,大胆做自己,活出精彩的人生👊👊👊
相关文章:

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
java 实现excel文件转pdf | 无水印 | 无限制
文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...

Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...

无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...

vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...
可靠性+灵活性:电力载波技术在楼宇自控中的核心价值
可靠性灵活性:电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中,电力载波技术(PLC)凭借其独特的优势,正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据,无需额外布…...
Qt Widget类解析与代码注释
#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码,写上注释 当然可以!这段代码是 Qt …...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...

关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...

使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...
基于服务器使用 apt 安装、配置 Nginx
🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...