MBG逆向工程(MyBatis+Spring下实现)

使用MyBatis Generator

在前面配置MyBatis时,根据不同的需求,操作不同的表,首先要创建与数据表对应的JavaBean,然后为这个实体类配置一个mapper映射文件,里面再写有SQL语句,如果你使用动态代理,那么还得要创建一个与xml文件对应的Mapper接口。到了后面与Spring整合后,SqlSessionFactory由Spring来管理,把加载Factory的代码也放入到xml中,节省了内存资源,不过,结果集实体类,Dao层接口和mapper映射文件也还是要自己动手配置。对于一个庞大的数据库来说,如果每一张表都要重复以上操作,为其编写增删查改的配置,工作量无疑会变得很大。这时可以配置MyBatis Generator,来根据我们的数据表,生成出符合条件的JavaBean,mapper文件和代理接口。可能你会想,自动生成的JavaBean没问题,但mapper映射文件里的增删查改操作,真的可以满足我们的自定义需求吗,例如我针对不同条件的查询,它要怎么实现?下面开看看MyBatis Generator的配置和实现,看看它为我们生成的这些文件是什么样的。

 

逆向工程配置

GeneratorConfig

首先是逆向工程中最重要的配置文件generatorConfig.xml,MBG怎么根据数据表生成这么多东西,关键就在于配置是否正确,逆向工程配置文件会指明连接的数据库,需要生成代码的数据表和它们的生成文件位置等,下面边看它的配置项边说:

<?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>
	<!-- 每一个context代表一个单独的逆向配置 -->
	<context id="TestGenerator" targetRuntime="MyBatis3">
		<commentGenerator>
			<!-- 取消自动生成注释 -->
			<property name="suppressAllComments" value="true" />
		</commentGenerator>
		<!-- 数据库连接信息 -->
		<jdbcConnection 
			driverClass="com.mysql.jdbc.Driver"
			connectionURL="jdbc:mysql://localhost:3306/mybatis_test"
			userId="root"
			password="12345">
		</jdbcConnection>
		
		<!-- 把JDBC DECIMAL和NUMERIC类型解析为Integer,为true时是解析成BigDecimal -->
		<javaTypeResolver>
			<property name="forceBigDecimals" value="false" />
		</javaTypeResolver>
		
		<!-- 配置生成的PO类(实体类)的位置,targetProject指示生成的位置 -->
		<javaModelGenerator targetPackage="com.sm.po"
			targetProject=".\src">
			<!-- 是否让schema作为包的后缀 -->
			<property name="enableSubPackages" value="false" />
			<!-- 数据库查询结果清除前后的空格 -->
			<property name="trimStrings" value="true" /> 
		</javaModelGenerator>
		
		<!-- 配置生成的mapper映射配置文件位置 -->
		<sqlMapGenerator targetPackage="com.sm.mapper"
			targetProject=".\src">
			<property name="enableSubPackages" value="false" />
		</sqlMapGenerator>
		
		<!-- 配置生成的Mapper代理接口位置 -->
		<javaClientGenerator type="XMLMAPPER"
			targetPackage="com.sm.mapper"
			targetProject=".\src">
			<property name="enableSubPackages" value="false" />
		</javaClientGenerator>
		
		<!-- 指定操作的数据库表 -->
		<table tableName="user"></table>
	</context>
</generatorConfiguration>

在generatorConfiguration标签对中,每一个context标签对里代表对一个逆向工程的配置。记下来简单配置数据库连接信息标签jdbcConnection,前面配置过MyBatis的相信大家都熟悉。下一个标签对javaTypeResolver中配置数据库的转换类型,对于JDBC中的DECIMAL和NUMERIC类型,我们配置其转换成Integer而不是BigDecimal。接下来的三个配置比较统一,配置pojo类,mapper映射文件和代理接口文件生成的位置,我们都把其放置在src目录下相应的包中。最后一项table标签配置逆向工程中我们要操作的数据表,这样,数据库,数据表以及文件生成位置我们都指定好了。MyBatis的逆向工程只有这么一个配置文件,十分重要,能不能生成正确使用的代码,依赖于这个xml文件。

逆向数据生成类

接下来就要创建一个生成代码的实现类,根据我们的配置信息,为我们创建代码。

package com.generator.main;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.api.ShellCallback;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;

public class GeneratorSqlMap {
	public void generator() throws Exception {
		// 集合warnings用来存放生成过程中的警告信息
		List<String> warnings = new ArrayList<String>();
		// overwrite指定是否覆盖重名文件
		boolean overwrite = true;
		// 加载逆向工程配置文件
		File generatorConfigFile = new File("generatorConfig.xml");
		// 配置解析类
		ConfigurationParser cp = new ConfigurationParser(warnings);
		// 配置解析类解析逆向工程配置文件,生成Configuration对象
		Configuration config = cp.parseConfiguration(generatorConfigFile);
		// 处理重复文件,指定Java或XML文件已存在情况下如何处理重复文件
		ShellCallback callback = new DefaultShellCallback(overwrite);
		// 逆向工程对象
		MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
		// 执行逆向文件生成操作
		myBatisGenerator.generate(null);
	}
	
	public static void main(String[] args) throws Exception {
		GeneratorSqlMap generatorSqlmap = new GeneratorSqlMap();
		generatorSqlmap.generator();
	}
}

第15行首先创建一个List集合存放警告信息,这是MyBatisGenerator类需要的参数。布尔类型变量overwrite用来标志,如果在生成文件时碰到名字相同的重复文件,如何处理,true标识新建的覆盖这些重复的旧文件。接下来读取我们的配置文件,使用File类来生成逆向工程配置文件对象,得到读取配置文件对象后,还需要一个配置解析类ConfigurationParser对象来解析配置文件,解析逆向工程配置文件后,最后生成Configuration对象。得到配置文件对象后,第27行在执行逆向文件生成操作前,创建一个ShellCallback对象,负责把配置文件中的targetProjcet和targetPackage文件路径和文件目录翻译,对于targetPackage,如果路径中的文件夹不存在,就会自动创建。对于targetProject,如果存在同名的文件,则根据你的配置,覆盖或者忽略重复的文件。

      解析配置文件对象创建好了,警告信息集合,重复文件处理也配置好,最后的最后,第27行创建逆向工程对象,把解析配置文件对象config,重复文件处理对象callback和警告信息集合warnings都作为参数传入初始化构造函数中,生成逆向工程对象,调用generate()逆向方法执行生成代码(JavaBean,mapper文件和代理接口)操作。

日志信息和生成代码

Generate()方法执行后,看到输出的日志信息:

DEBUG [main] - Retrieving column information for table "user"
DEBUG [main] - Found column "id", data type 4, in table "mybatis_test..user"
DEBUG [main] - Found column "username", data type 12, in table "mybatis_test..user"
DEBUG [main] - Found column "password", data type 12, in table "mybatis_test..user"
DEBUG [main] - Found column "gender", data type 12, in table "mybatis_test..user"
DEBUG [main] - Found column "email", data type 12, in table "mybatis_test..user"
DEBUG [main] - Found column "province", data type 12, in table "mybatis_test..user"
DEBUG [main] - Found column "city", data type 12, in table "mybatis_test..user"
DEBUG [main] - Found column "birthday", data type 91, in table "mybatis_test..user"
DEBUG [main] - Found column "age", data type 4, in table "mybatis_test..user"

因为我们在配置文件中正确配置的table标签,所以MyBatis Generator在user表中找到了各个字段,以及它们的数据类型,所在的数据表。再看看逆向生成的代码:

根据逆向工程配置文件中三个文件的配置项targetPackage,MBG为我们生成了两个包,com.sm.po和com.sm.mapper,并且根据上面获得的数据表信息,创建出了实体类User.java以及一个查询包装类UserExample.java,mapper映射文件UserMapper.xml和代理接口UserMapper.java。User类就是数据表user中字段的映射实体类,UserMapper.java是我们的代理接口,来看看里面MBG都为我们实现了哪些方法:

package com.sm.mapper;

import com.sm.po.User;
import com.sm.po.UserExample;
import java.util.List;
import org.apache.ibatis.annotations.Param;

public interface UserMapper {
    int countByExample(UserExample example);

    int deleteByExample(UserExample example);

    int deleteByPrimaryKey(Integer id);

    int insert(User record);

    int insertSelective(User record);

    List<User> selectByExample(UserExample example);

    User selectByPrimaryKey(Integer id);

    int updateByExampleSelective(@Param("record") User record, @Param("example") UserExample example);

    int updateByExample(@Param("record") User record, @Param("example") UserExample example);

    int updateByPrimaryKeySelective(User record);

    int updateByPrimaryKey(User record);
}

可以看到,第一个countByExamle()方法提供了数据统计操作,会给句UserExample查询包装类给出的查询条件,查询出结果总数。

selectByPrimaryKey()方法:根据传入的id查询用户信息。

selectByExample()方法:根据传入的查询包装类UserExample查询出符合条件的用户信息。

UpdateByPrimaryKey()方法:根据传入的User类对象对符合条件的用户信息做全部修改。

UpdateByPrimaryKeySelective()方法:则是根据传入的User类对象对符合条件的用户信息做部分修改。

插入操作和删除操作和上面的都类似,这里就不一一列出。

Mapper映射配置文件

还有一个就是MyBatis Generator为我们生成的mapper文件,来看看里面的resultMap和SQL语句:

里面都是resultMap结果集映射配置和各种数据库操作语句,文件比较长,我们就不一一看了,大家可以到文末我上传的GitHub地址里查看。

MyBatis为我们处理好一切后,最后就来测试一下生成的数据文件是否能正确执行。

 

测试用例

把逆向工程生成的JavaBean,mapper映射配置和代理接口文件都放到MyBatis或者MyBatis-Spring整合环境中,这里我使用的是MyBatis和Spring整合,然后根据代理接口中的方法,编写简单的测试用例。

增删查改

首先来看简单的查询代码:

// 简单查询
	public void FindUserByIdTest() throws Exception {
		setup();
		//动态代理方法
		UserMapper userMapper = (UserMapper) applicationContext.getBean("userMapper");
		User user = userMapper.selectByPrimaryKey(4);
		
		StringBuffer result = new StringBuffer();
		result.append("用户名: " + user.getUsername() + "\r\n");
		result.append("性别: " + user.getGender() + "\r\n");
		result.append("电子邮箱: " + user.getEmail() + "\r\n");
		result.append("省份: " + user.getProvince() + "\r\n");
		result.append("城市: " + user.getCity() + "\r\n");
		
		System.out.println(result.toString());
	}

根据传入的id参数查询对应的用户信息,相信你们也可以写出这样的操作语句,不再累述了!下一个,插入操作:

// 插入操作
	public void UserInsert() throws Exception {
		setup();
		// 动态代理接口
		UserMapper userMapper = (UserMapper) applicationContext.getBean("userMapper");
		
		// 构建插入对象
		User insertUser = new User();
		insertUser.setUsername("理莎");
		insertUser.setPassword("9497");
		insertUser.setGender("女");
		insertUser.setEmail("[email protected]");
		insertUser.setProvince("广东省");
		insertUser.setCity("广州市");
		
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		Date uBirthday = sdf.parse("1997-3-27");
		insertUser.setBirthday(uBirthday);
		
		// 插入操作
		userMapper.insert(insertUser);
		
	}

创建好要插入的User对象信息,作为参数传入insert()方法,来看下执行后的日志信息:

最后看删除操作:

// 删除操作
	public void UserDelete() throws Exception {
		setup();
		UserMapper userMapper = (UserMapper) applicationContext.getBean("userMapper");
		
		userMapper.deleteByPrimaryKey(9);
		User deleteUser = userMapper.selectByPrimaryKey(9);
		if(deleteUser == null) {
			System.out.println("删除成功!");
		} else {
			System.out.println("删除失败!");
		}
	}

MBG逆向生成的文件都不是定死的,只是方便大家对于一些简单的如实体类配置,上面这些简单的增删查改操作,都帮你配置好,我们可以对其修改然后再使用,对于一些复杂的操作,我们可以修改里面的代码,以适用于我们的需求。

自定义查询

最后,来看看MyBatis Generator为我们提供的UserExample查询包装类,我们可以用它来做一些复杂的查询,如条件查询,下面来看一个简单的例子:

// UserExample类:复杂查询或修改操作包装类
	// UserExample类自定义查询
	public void UserExampleSelect() throws Exception {
		setup();
		UserExample userExample = new UserExample();
		//创建Criteria对象来构造查询条件
		UserExample.Criteria criteria = userExample.createCriteria();
		// 动态代理接口
		UserMapper userMapper = (UserMapper) applicationContext.getBean("userMapper");
		// 存放结果集
		StringBuffer result = new StringBuffer();
		
		// 构建查询条件,性别,出生日期范围,email不空
		criteria.andGenderEqualTo("女");
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		criteria.andBirthdayBetween(sdf.parse("1998-01-01"), sdf.parse("2000-01-01"));
		criteria.andEmailIsNotNull();
		
		List<User> resultList = userMapper.selectByExample(userExample);
		for(int i=0; i<resultList.size(); i++) {
			User user = resultList.get(i);
			result.append("用户名: " + user.getUsername() + "\r\n");
			result.append("性别: " + user.getGender() + "\r\n");
			result.append("电子邮箱: " + user.getEmail() + "\r\n");
			result.append("省份: " + user.getProvince() + "\r\n");
			result.append("城市: " + user.getCity() + "\r\n");
			
			System.out.println(result.toString());
			result.setLength(0);
		}
	}

首先创建UserExample类对象,最后要作为参数传入查询方法中的,然后调用userExample对象的createCriteria()方法,实例化一个UserExample.Criteria对象,它负责保存我们自定义的查询条件。第14行开始就是构建查询条件了,包括性别为女,出生日期范围以及电子邮箱不为空。第19行调用selectByExample()方法做自定义查询,由于查询得到的结果可能不止一条,所以我们用List集合存放查询结果,最后看看执行结果:

 

完整代码已上传GitHub:

https://github.com/justinzengtm/SSM-Framework/tree/master/MyBatisGenerator

发布了97 篇原创文章 · 获赞 71 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/justinzengTM/article/details/101100795