Mybatis现在已经是非常受企业以及程序员喜爱的持久层框架之一了,同时Mybatis为了迎合java编程的趋势(面向接口编程),有了Mapper接口文件,更加方便了我们日常的开发,但与此同时,又出现了新的问题,跟随着互联网时代的热浪,大部分企业都开始追随着互联网公司做分布式架构,朝着高并发走,同时也需要优化自己的数据库,分表分库,尽量让自己的查询少关联,而针对这样的情况,我们程序员也不得不每个表都写一个实体类,写个mapper接口,再写个xml文件,实施上Mybatis已经帮我们想好了解决方法,可以自动生成单表的实体类,接口文件,xml映射文件,并且为了能够按条件进行单表查询还有另外两个类,Example和Criteria(“妈妈”再也不用为了100张单表查询看着我们写实体类了),单表查询再也不用写sql了。
今天的任务就是实现逆向工程,首先我们可以通过mybatis的官方网站或者CSDN上下载逆向工程的包,这步我就直接省略了,现在网上资源太多,后面我会撸代码,你们一看包名就知道怎么找了。
其实逆向工程正如其名,这是一个工程,而这个工程的作用就是生成上文中提到的4个类,他的main方法所在的类大家可以不用理会,我们主要用的是他的配置文件。
这也是我们最关注的部分,要用逆向工程就要会配置他的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>
<context id="testTables" targetRuntime="MyBatis3">
<commentGenerator>
<!-- 是否去除自动生成的注释 true:是 : false:否 -->
<property name="suppressAllComments" value="true" />
</commentGenerator>
<!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/simon"
userId="root"
password="lcx66297022">
</jdbcConnection>
<!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL 和
NUMERIC 类型解析为java.math.BigDecimal -->
<javaTypeResolver>
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<!-- targetProject:生成PO类的位置 -->
<javaModelGenerator targetPackage="com.simon.entity"
targetProject=".\src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
<!-- 从数据库返回的值被清理前后的空格 -->
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- targetProject:mapper映射文件生成的位置 -->
<sqlMapGenerator targetPackage="com.simon.dao"
targetProject=".\src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
</sqlMapGenerator>
<!-- targetPackage:mapper接口生成的位置 -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.simon.dao"
targetProject=".\src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
</javaClientGenerator>
<!-- 指定数据库表 -->
<table schema="" tableName="simon"></table>
</context>
</generatorConfiguration>
其实在这个配置文件中数据库的配置我就不用说了
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/simon"
userId="root"
password="lcx66297022">
</jdbcConnection>
最主要的也是大家最关心的是这几个包的问题,我们都知道需要生成4个文件,3个java的一个xml的,我们先说实体类的。
实体类
<javaModelGenerator targetPackage="com.simon.entity"
targetProject=".\src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
<!-- 从数据库返回的值被清理前后的空格 -->
<property name="trimStrings" value="true" />
</javaModelGenerator>
TargetPackage就是你现在要将生成的试题类放在哪里的问题,我一般是直接放到我项目中的包里,也是为了图省事。
.\src:就是你当前的项目中,当然也可以指定其他的路径
不过还有一种需求,假如我希望我生成的类都继承一个类,Mybatis也提供了相应的属性
<property name="rootClass"value="com.simon.Domain" />
XML映射文件
<!-- targetProject:mapper映射文件生成的位置 -->
<sqlMapGenerator targetPackage="com.simon.dao"
targetProject=".\src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
</sqlMapGenerator>
Mapper接口
<!-- targetPackage:mapper接口生成的位置 -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.simon.dao"
targetProject=".\src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
</javaClientGenerator>
我把映射文件和接口放在一个类下面了,当然如果你想放在其他的地方都可以,我在这里主要是举例。
最后的步骤就是指定需要自动生成哪张表,或者哪几张表。
指定数据库中的表
<!-- 指定数据库表 -->
<table schema="" tableName="simon"></table>
到此,配置文件结束了,我们要生成simon这个表的文件还需要最后一步,那就是运行逆向工程。
public class GeneratorSqlmap {
public void generator() throws Exception{
List<String> warnings = new ArrayList<String>();
boolean overwrite = true;
//指定 逆向工程配置文件
File configFile = new File("generatorConfig.xml");
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);
}
public static void main(String[] args) throws Exception {
try {
GeneratorSqlmap generatorSqlmap = new GeneratorSqlmap();
generatorSqlmap.generator();
} catch (Exception e) {
e.printStackTrace();
}
}
}
这是个main方法,右键run就可以了,我们可以看看结果
控制台输出
2017-07-26 17:37:02,628 [main] DEBUG [org.mybatis.generator.internal.db.DatabaseIntrospector] - Retrieving column information for table "simon"
2017-07-26 17:37:02,648 [main] DEBUG [org.mybatis.generator.internal.db.DatabaseIntrospector] - Found column "simonid", data type 4, in table "simon..simon"
2017-07-26 17:37:02,648 [main] DEBUG [org.mybatis.generator.internal.db.DatabaseIntrospector] - Found column "simonname", data type 12, in table "simon..simon"
2017-07-26 17:37:02,648 [main] DEBUG [org.mybatis.generator.internal.db.DatabaseIntrospector] - Found column "simonage", data type 4, in table "simon..simon"
控制台打出的内容还是很详细的对吧,这就证明逆向工程正常运行了,那我们看看生成的文件在哪里。
多出来了两个包,这就是逆向工程生成的,我们来看下这两个包里的类
从名称上已经看得出来了吧,但是其中有个类可能很多没有用过逆向工程的会不太清楚,这就是mybatis逆向工程能让你做到依据sql都不用写的工具。如果感兴趣的朋友可以去看看这个类里面的代码,大致的思路其实就是将你的查询条件拼成一个sql语句的片段,再执行,
我们通过一个例子来看看mybatis逆向工程的查询语句如何写。为此我简单的建了张表
写Demo之前我们先将生成的4个类放到我们的工程中。
可以对比之前的逆行工程中生成的包名,和这里是对应上的,这是我的习惯,这并不是固定的,是可以配置的,在此为了省事就这么做了。
逆向工程Demo
表和类都准备好了,那么逆向工程到底给我们带来了什么便利呢?
需求:
查询ID=1的数据
如果不是逆向工程,我们是需要些sql语句的,而现在,只要是单表查询,我们就不用再写sql了。
创建一个测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath*:/spring/applicationContext-mvc.xml","classpath*:/spring/applicationContext-mybatis.xml"})
public class GeneratorTest {
}
测试类用了Spring整合的junit,关于这里,大家不要觉得疑惑,你也可以先用ApplicationContext对象去做测试,如果想要了解的话网上有很多的资料。我们一步步来操作,我们既然生成了mapper文件,其实和我们之前自己写mapper道理是一样的,原来怎么用,现在也一样。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath*:/spring/applicationContext-mvc.xml","classpath*:/spring/applicationContext-mybatis.xml"})
public class GeneratorTest {
@Autowired
private SimonMapper mapper;
@Test
public void testOne(){
}
}
调用mapper的查询方法
@Test
public void testOne(){
mapper.selectByExample(example);
}
发现这个方法和我们之前的不一样,之前我们自己写,自己传参数,而在这里他需要传入一个example,我们看下这个example是什么东西?
Example是逆向工程生成的一个类,而我们查询的时候需要传入这个类,那么我们来创建一个Example类。
创建Example类
@Test
public void testOne(){
SimonExample example = new SimonExample();
mapper.selectByExample(example);
}
写了查询语句应该是有返回值的对吧,在这里返回的是一个list集合,我们需要遍历这个集合获取到数据
@Test
public void testOne(){
SimonExample example = new SimonExample();
List<Simon> list = mapper.selectByExample(example);
for (Simon simon : list) {
System.out.println(simon);
}
}
查看结果
Simon [simonid=1, simonname=赵六, simonage=13]
Simon [simonid=2, simonname=赵六, simonage=13]
Simon [simonid=3, simonname=王五, simonage=13]
Simon [simonid=4, simonname=王五, simonage=13]
Simon [simonid=5, simonname=马四, simonage=13]
Simon [simonid=7, simonname=科技时代, simonage=13]
Simon [simonid=8, simonname=赵六, simonage=13]
Simon [simonid=9, simonname=赵六, simonage=13]
我们发现结果出现了所有的数据,我们的需求是ID=1的数据,也就是说我们需要给查询语句添加查询条件,这时候就需要另一个类了,Criteria,这个类的作用就是给我们的查询语句添加条件,至于如何做到的大家可以看看example这个类,实现并不难,我们来实际操作下。
先创建Criteria类,这个类是Example的内部类
@Test
public void testOne(){
SimonExample example = new SimonExample();
Criteria criteria = example.createCriteria();
List<Simon> list = mapper.selectByExample(example);
for (Simon simon : list) {
System.out.println(simon);
}
}
用Criteria添加查询条件(查询ID=1的数据)
@Test
public void testOne(){
SimonExample example = new SimonExample();
Criteria criteria = example.createCriteria();
criteria.andSimonidEqualTo(1);
List<Simon> list = mapper.selectByExample(example);
for (Simon simon : list) {
System.out.println(simon);
}
}
结果
到这里我们的Demo就结束了,其实用法和之前类似,但是多了一个Example类和Criteria类,这两个类的主要作用就是给你的sql加查询条件的,
从第一个例子中你会发现,当我不创建Example的内部类Criteria的时候,就相当于没有添加任何查询条件,那么查询的就是所有结果
返回值是List集合,不论查询一个还是多个,如果是一个你可以用list.get(0)获取到,就不用遍历了。
逆向工程还有insert方法,update方法,delete方法,这些大家可以尝试着去做做,其实逆向工程生成的代码不同的地方就在于如何给查询加条件,也就是Example和Criteria,多试几次你就明白了。