在前面配置MyBatis时,根据不同的需求,操作不同的表,首先要创建与数据表对应的JavaBean,然后为这个实体类配置一个mapper映射文件,里面再写有SQL语句,如果你使用动态代理,那么还得要创建一个与xml文件对应的Mapper接口。到了后面与Spring整合后,SqlSessionFactory由Spring来管理,把加载Factory的代码也放入到xml中,节省了内存资源,不过,结果集实体类,Dao层接口和mapper映射文件也还是要自己动手配置。对于一个庞大的数据库来说,如果每一张表都要重复以上操作,为其编写增删查改的配置,工作量无疑会变得很大。这时可以配置MyBatis Generator,来根据我们的数据表,生成出符合条件的JavaBean,mapper文件和代理接口。可能你会想,自动生成的JavaBean没问题,但mapper映射文件里的增删查改操作,真的可以满足我们的自定义需求吗,例如我针对不同条件的查询,它要怎么实现?下面开看看MyBatis Generator的配置和实现,看看它为我们生成的这些文件是什么样的。
首先是逆向工程中最重要的配置文件generatorConfig.xml,MBG怎么根据数据表生成这么多东西,关键就在于配置是否正确,逆向工程配置文件会指明连接的数据库,需要生成代码的数据表和它们的生成文件位置等,下面边看它的配置项边说:
在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 warnings = new ArrayList();
// 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 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类对象对符合条件的用户信息做部分修改。
插入操作和删除操作和上面的都类似,这里就不一一列出。
还有一个就是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 resultList = userMapper.selectByExample(userExample);
for(int i=0; i
首先创建UserExample类对象,最后要作为参数传入查询方法中的,然后调用userExample对象的createCriteria()方法,实例化一个UserExample.Criteria对象,它负责保存我们自定义的查询条件。第14行开始就是构建查询条件了,包括性别为女,出生日期范围以及电子邮箱不为空。第19行调用selectByExample()方法做自定义查询,由于查询得到的结果可能不止一条,所以我们用List集合存放查询结果,最后看看执行结果:
完整代码已上传GitHub:
https://github.com/justinzengtm/SSM-Framework/tree/master/MyBatisGenerator