Mybatis3详解(十三)----Mybatis逆向工程
1、什么是逆向工程
Mybatis的逆向工程就是由代码生成器生成我们需要的代码和映射文件。我们在编写Mybatis程序时,基本都是围绕着pojo类,Mapper接口,Mapper.xml文件等文件来进行的。如果实际开发中数据库的表特别多,那么我们需要手动去写每一张表的pojo类,Mapper接口,Mapper.xml文件,这显然需要花费巨大的精力,而且可能由于表字段太多,哪里写错了都难以排除。所以我们在实际开发中,一般使用逆向工程方式来自动生成所需的文件,这也是企业中一种非常常见的方法。
注意:在使用逆向工程生成代码文件的时候,最好额外创建一个项目,不要在原来的项目中使用,因为如果你在原项目中有相同名字的文件,那么就会被新生成的文件所覆盖,导致之前写的代码没了,有一定的风险。所以实际开发中,我们一般新建一个项目,然后将生成的文件复制到自己的所需的工程中。
2、逆向工程生成代码
①、首先创建maven项目
项目整体目录:
导入maven依赖:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <!-- Mybatis --> < dependency > < groupId >org.mybatis</ groupId > < artifactId >mybatis</ artifactId > < version >3.5.6</ version > </ dependency > <!-- mysql驱动 --> < dependency > < groupId >mysql</ groupId > < artifactId >mysql-connector-java</ artifactId > < version >8.0.21</ version > </ dependency > <!-- 日志处理 --> < dependency > < groupId >log4j</ groupId > < artifactId >log4j</ artifactId > < version >1.2.17</ version > </ dependency > <!-- 逆向工程 --> < dependency > < groupId >org.mybatis.generator</ groupId > < artifactId >mybatis-generator-core</ artifactId > < version >1.4.0</ version > </ dependency > |
②、创建日志文件log4j.properties
01 02 03 04 05 06 07 08 | # Set root category priority to INFO and its only appender to CONSOLE. #log4j.rootCategory=INFO, CONSOLE debug info warn error fatal log4j.rootCategory=debug, CONSOLE # CONSOLE is set to be a ConsoleAppender using a PatternLayout. log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n |
③、创建generatorConfig.xml配置文件
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | <? 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"表示生成简易版本,这里创建原始版本,参数为MyBatis3--> < context id="testTables" targetRuntime="MyBatis3"> < commentGenerator > <!-- 是否去除自动生成的注释。true:是;false:否 --> < property name="suppressAllComments" value="true" /> </ commentGenerator > <!--数据库连接的信息:驱动类、连接地址、用户名、密码 --> < jdbcConnection driverClass="com.mysql.cj.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/mybatis?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8" userId="root" password="root"> </ jdbcConnection > <!-- 默认false,把JDBC DECIMAL和NUMERIC类型解析为Integer,为true时把JDBC DECIMAL 和 NUMERIC 类型解析为java.math.BigDecimal --> < javaTypeResolver > < property name="forceBigDecimals" value="false" /> </ javaTypeResolver > <!-- targetProject:POJO类生成的位置 --> < javaModelGenerator targetPackage="com.thr.pojo" targetProject="./src/main/java"> <!-- enableSubPackages:是否让schema作为包的后缀 --> < property name="enableSubPackages" value="false" /> <!-- 从数据库返回的值被清理前后的空格 --> < property name="trimStrings" value="true" /> </ javaModelGenerator > <!-- targetProject:mapper映射文件生成的位置 --> < sqlMapGenerator targetPackage="com.thr.mapper" targetProject="./src/main/resources"> <!-- enableSubPackages:是否让schema作为包的后缀 --> < property name="enableSubPackages" value="false" /> </ sqlMapGenerator > <!-- targetPackage:mapper接口生成的位置 --> < javaClientGenerator type="XMLMAPPER" targetPackage="com.thr.mapper" targetProject="./src/main/java"> <!-- enableSubPackages:是否让schema作为包的后缀 --> < property name="enableSubPackages" value="false" /> </ javaClientGenerator > <!-- 指定生成哪些数据库表,要和数据库中对应,不能写错了,这里以t_user表为例,可以写多个;domainObjectName是要生成的实体类名称--> < table schema="mybatis" tableName="t_user"/> <!-- 有些表的字段需要指定java类型 <table schema="" tableName=""> <columnOverride column="" javaType="" /> </table> --> </ context > </ generatorConfiguration > |
注意:serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8中的 & 要改成转义字符 & 这里传上来页面自动给转成了 &。
还有就是不同的数据库中不能含有相同的表,例如数据库A有t_user表,数据库B也有t_user表,那么到时候代码不知道生成哪个,而我恰好生成的是我们不需要的那个。啊?你说上面不是指定了数据库吗,怎么会到读取到其它数据库的表,不好意思,我试了不下十遍,最后我把其它数据库同名的表删除才成功的。如果你没有这种情况那更好咯。
④、创建逆向工程核心生成代码GeneratorSql.java
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | package com.thr.generator; 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; /** * 逆向工程核心生成代码 */ public class GeneratorSql { public void generator() throws Exception { List<String> warnings = new ArrayList<>(); boolean overwrite = true ; // 指定逆向工程配置文件 String file = GeneratorSql. class .getResource( "/generatorConfig.xml" ).getFile(); 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 ); } // 执行main方法以生成代码 public static void main(String[] args) { try { GeneratorSql generatorSql = new GeneratorSql(); generatorSql.generator(); } catch (Exception e) { e.printStackTrace(); } } } |
⑤、运行逆向工程核心生成代码
运行上面的程序,如果控制台打印了如下日志,说明生成代码成功了。
然后我们再看项目就会发现生成了如下文件:
下面我们就来学习如何使用它们。
3、逆向工程举例
首先我们将上面生成的文件复制到目标项目中。在使用逆向工程举例之前,先来介绍生成的文件有哪些东西:
(1)、TUserMapper接口生成的方法介绍:
- long countByExample(TUserExample example):按条件计数
- int deleteByExample(TUserExample example):按条件删除
- int deleteByPrimaryKey(Integer id):按主键删除
- int insert(TUser record):插入数据(返回值为ID)
- int insertSelective(TUser record):插入数据,只插入值不为null的字段,内部动态sql判断
- List<TUser> selectByExample(TUserExample example):按条件查询,传入null表示查询所有
- TUser selectByPrimaryKey(Integer id):按主键查询
- int updateByExampleSelective(@Param("record") TUser record, @Param("example") TUserExample example):按条件更新值不为null的字段
- int updateByExample(@Param("record") TUser record, @Param("example") TUserExample example):按条件更新
- int updateByPrimaryKeySelective(TUser record):按主键更新值不为null的字段
- int updateByPrimaryKey(TUser record):按主键更新
测试不带条件的方法:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | //Mybatis的测试 public class MybatisTest { //定义 SqlSession private SqlSession sqlSession = null ; //定义 TUserMapper对象 private TUserMapper mapper = null ; @Before //在测试方法执行之前执行 public void getSqlSession(){ //1、加载 mybatis 全局配置文件 InputStream is = MybatisTest. class .getClassLoader().getResourceAsStream( "mybatis-config.xml" ); //2、创建SqlSessionFactory对象 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); //3、根据 sqlSessionFactory 产生session sqlSession = sqlSessionFactory.openSession(); //4、创建Mapper接口的的代理对象,getMapper方法底层会通过动态代理生成TUserMapper的代理实现类 mapper = sqlSession.getMapper(TUserMapper. class ); } @After //在测试方法执行完成之后执行 public void destroy() throws IOException { sqlSession.commit(); sqlSession.close(); } //查询所有用户信息 @Test public void selectAllUser(){ List<TUser> tUsers = mapper.selectByExample( null ); //传入null表示查询所有 for (TUser tUser : tUsers) { System.out.println(tUser); } } //根据用户id查询用户 @Test public void selectByUserId(){ TUser tUser = mapper.selectByPrimaryKey( 1 ); System.out.println(tUser); } //添加用户信息 @Test public void insertUser(){ TUser tUser = new TUser(); tUser.setUsername( "凡尔赛" ); tUser.setAge( 18 ); tUser.setBirthday( new Date()); tUser.setSex( "0" ); tUser.setAddress( "漂亮国" ); int i = mapper.insertSelective(tUser); System.out.println(i> 0 ? "添加成功" : "添加失败" ); } //更新用户信息 @Test public void updateUser(){ TUser tUser = new TUser(); tUser.setId( 8 ); //这里要设置id才能修改成功,否则不知道修改哪一条数据 tUser.setUsername( "川建国" ); tUser.setAge( 50 ); tUser.setBirthday( new Date()); tUser.setSex( "1" ); tUser.setAddress( "漂亮国" ); int i = mapper.updateByPrimaryKeySelective(tUser); System.out.println(i> 0 ? "修改成功" : "修改失败" ); } //删除用户信息 @Test public void deleteUser(){ int i = mapper.deleteByPrimaryKey( 8 ); System.out.println(i> 0 ? "删除成功" : "删除失败" ); } } |
(2)、TUserExample条件扩展类介绍:
上面的测试方法是不带条件的操作,那么接下来学习一下按条件如何进行增删改查操作,我们在逆向工程中已经生成了这个类TUserExample,这个类就是一个条件扩展类,里面定义了一系列方法用来做条件,比如:排序、去重、大于、小于、等于、模糊查询、数据在某某之间等等。
我们在TUserExample类中可以看到定义了一个内部类GeneratedCriteria,这个内部类就定义了一系列条件的方法,这些条件最后都会拼接在SQL中,但是我们一般不用它,都用它的子类Criteria来进行操作,Criteria继承了内部类GeneratedCriteria。
简单举例:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | //Mybatis的测试 public class MybatisTest1 { //定义 SqlSession private SqlSession sqlSession = null ; //定义 UserMapper对象 private TUserMapper mapper = null ; @Before //在测试方法执行之前执行 public void getSqlSession(){ //1、加载 mybatis 全局配置文件 InputStream is = MybatisTest1. class .getClassLoader().getResourceAsStream( "mybatis-config.xml" ); //2、创建SqlSessionFactory对象 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is); //3、根据 sqlSessionFactory 产生session sqlSession = sqlSessionFactory.openSession(); //4、创建Mapper接口的的代理对象,getMapper方法底层会通过动态代理生成UserMapper的代理实现类 mapper = sqlSession.getMapper(TUserMapper. class ); } @After //在测试方法执行完成之后执行 public void destroy() throws IOException { sqlSession.commit(); sqlSession.close(); } //模糊查询用户信息 @Test public void selectUserLike(){ TUserExample example = new TUserExample(); TUserExample.Criteria criteria = example.createCriteria(); //模糊条件 criteria.andUsernameLike( "%三%" ); /*sql语句相当于:select id, username, age, birthday, sex, address from t_user WHERE ( username like ? )*/ List<TUser> tUsers = mapper.selectByExample(example); for (TUser tUser : tUsers) { System.out.println(tUser); } } //查询年龄在18-30岁之间的用户信息 @Test public void selectUserBetween(){ TUserExample example = new TUserExample(); TUserExample.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<TUser> tUsers = mapper.selectByExample(example); for (TUser tUser : tUsers) { System.out.println(tUser); } } //查询用户名A或B @Test public void selectUserOr(){ TUserExample example = new TUserExample(); TUserExample.Criteria criteria1 = example.createCriteria(); criteria1.andUsernameEqualTo( "黄飞鸿" ); TUserExample.Criteria criteria2 = example.createCriteria(); criteria2.andUsernameEqualTo( "马保国" ); //将criteria2条件拼接在 or 关键字字后面 example.or(criteria2); /*sql语句相当于:select id, username, age, birthday, sex, address from t_user WHERE ( username = ? ) or( username = ? )*/ List<TUser> tUsers = mapper.selectByExample(example); for (TUser tUser : tUsers) { System.out.println(tUser); } } //根据用户名删除用户 @Test public void deleteUserExample(){ TUserExample example = new TUserExample(); TUserExample.Criteria criteria = example.createCriteria(); criteria.andUsernameEqualTo( "凡尔赛" ); //sql语句相当于:delete from t_user WHERE ( username = ? ) int i = mapper.deleteByExample(example); System.out.println(i> 0 ? "删除成功" : "删除失败" ); } } |
至此Mybatis的逆向工程就全部介绍完成了,说难也不是特别难,只要一步步自己去实现,去理解一遍,是非常简单的,可能复杂一点的是那个XxxExample类,但如果自己多举几个例子也不难。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· 因为Apifox不支持离线,我果断选择了Apipost!