Spring+SpringMVC+MyBatis深入学习及搭建(十)——MyBatis逆向工程
转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/6973266.html
前面讲到:Spring+SpringMVC+MyBatis 深入学习及搭建 (九)——MyBatis 和 Spring 整合
使用官方网站的 mapper 自动生成工具 mybatis-generator-core-1.3.2 来生成 po 类和 mapper 映射文件。
1. 什么是逆向工程
mybatis 需要程序员自己编写 sql 语句,mybatis 官方提供逆向工程可以针对单表自动生成 mybatis 执行所需要的代码(mapper.java、mapper.xml、po...)
企业实际开发中,常用的逆向工程方式:
由数据库的表生成 java 代码。
2. 下载逆向工程
3. 使用方法(要求会用)
为了防止后期数据库表修改、扩展,需求修改等原因,更新自动生成的 po,mapper 覆盖有误。我们新建专门逆向生成的项目 generatorSqlmapCustom,再按需求将自动生成的 po,mapper 等拷贝到项目中去。
3.1 运行逆向工程
建议使用 java 程序方式,不依赖开发工具。
3.2mapper 生成配置文件
在 gengeratorConfig.xml 中配置 mapper 生成的详细信息,注意改下几点:
(1)添加要生成的数据库表;
(2)po 文件所在包路径;
(3)mapper 文件所在包路径。
配置文件如下:
<?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/mybatisdemo" userId="root"
password="">
</jdbcConnection>
<!-- <jdbcConnection driverClass="oracle.jdbc.OracleDriver"
connectionURL="jdbc:oracle:thin:@127.0.0.1:1521:yycg"
userId="yycg"
password="yycg">
</jdbcConnection> --><span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)"> 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL 和 NUMERIC 类型解析为java.math.BigDecimal </span><span style="color: rgba(0, 128, 0, 1)">--></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">javaTypeResolver</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="forceBigDecimals"</span><span style="color: rgba(255, 0, 0, 1)"> value</span><span style="color: rgba(0, 0, 255, 1)">="false"</span> <span style="color: rgba(0, 0, 255, 1)">/></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">javaTypeResolver</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)"> targetProject:生成PO类的位置 </span><span style="color: rgba(0, 128, 0, 1)">--></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">javaModelGenerator </span><span style="color: rgba(255, 0, 0, 1)">targetPackage</span><span style="color: rgba(0, 0, 255, 1)">="joanna.yan.po"</span><span style="color: rgba(255, 0, 0, 1)"> targetProject</span><span style="color: rgba(0, 0, 255, 1)">=".\src"</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)"> enableSubPackages:是否让schema作为包的后缀 </span><span style="color: rgba(0, 128, 0, 1)">--></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="enableSubPackages"</span><span style="color: rgba(255, 0, 0, 1)"> value</span><span style="color: rgba(0, 0, 255, 1)">="false"</span> <span style="color: rgba(0, 0, 255, 1)">/></span> <span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)"> 从数据库返回的值被清理前后的空格 </span><span style="color: rgba(0, 128, 0, 1)">--></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="trimStrings"</span><span style="color: rgba(255, 0, 0, 1)"> value</span><span style="color: rgba(0, 0, 255, 1)">="true"</span> <span style="color: rgba(0, 0, 255, 1)">/></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">javaModelGenerator</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)"> targetProject:mapper映射文件生成的位置 </span><span style="color: rgba(0, 128, 0, 1)">--></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">sqlMapGenerator </span><span style="color: rgba(255, 0, 0, 1)">targetPackage</span><span style="color: rgba(0, 0, 255, 1)">="joanna.yan.mapper"</span><span style="color: rgba(255, 0, 0, 1)"> targetProject</span><span style="color: rgba(0, 0, 255, 1)">=".\src"</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)"> enableSubPackages:是否让schema作为包的后缀 </span><span style="color: rgba(0, 128, 0, 1)">--></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">property </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="enableSubPackages"</span><span style="color: rgba(255, 0, 0, 1)"> value</span><span style="color: rgba(0, 0, 255, 1)">="false"</span> <span style="color: rgba(0, 0, 255, 1)">/></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">sqlMapGenerator</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)"> targetPackage:mapper接口生成的位置 </span><span style="color: rgba(0, 128, 0, 1)">--></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">javaClientGenerator </span><span style="color: rgba(255, 0, 0, 1)">type</span><span style="color: rgba(0, 0, 255, 1)">="XMLMAPPER"</span><span style="color: rgba(255, 0, 0, 1)"> targetPackage</span><span style="color: rgba(0, 0, 255, 1)">="joanna.yan.mapper"</span><span style="color: rgba(255, 0, 0, 1)"> targetProject</span><span style="color: rgba(0, 0, 255, 1)">=".\src"</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)"> enableSubPackages:是否让schema作为包的后缀 </span><span style="color: rgba(0, 128, 0, 1)">--></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">p </span><span style="color: rgba(255, 0, 0, 1)">roperty name</span><span style="color: rgba(0, 0, 255, 1)">="enableSubPackages"</span><span style="color: rgba(255, 0, 0, 1)"> value</span><span style="color: rgba(0, 0, 255, 1)">="false"</span> <span style="color: rgba(0, 0, 255, 1)">/></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">javaClientGenerator</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)"> 指定数据库表 </span><span style="color: rgba(0, 128, 0, 1)">--></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">table </span><span style="color: rgba(255, 0, 0, 1)">tableName</span><span style="color: rgba(0, 0, 255, 1)">="items"</span><span style="color: rgba(0, 0, 255, 1)">></</span><span style="color: rgba(128, 0, 0, 1)">table</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">table </span><span style="color: rgba(255, 0, 0, 1)">tableName</span><span style="color: rgba(0, 0, 255, 1)">="orders"</span><span style="color: rgba(0, 0, 255, 1)">></</span><span style="color: rgba(128, 0, 0, 1)">table</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">table </span><span style="color: rgba(255, 0, 0, 1)">tableName</span><span style="color: rgba(0, 0, 255, 1)">="orderdetail"</span><span style="color: rgba(0, 0, 255, 1)">></</span><span style="color: rgba(128, 0, 0, 1)">table</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 0, 255, 1)"><</span><span style="color: rgba(128, 0, 0, 1)">table </span><span style="color: rgba(255, 0, 0, 1)">tableName</span><span style="color: rgba(0, 0, 255, 1)">="user"</span><span style="color: rgba(0, 0, 255, 1)">></</span><span style="color: rgba(128, 0, 0, 1)">table</span><span style="color: rgba(0, 0, 255, 1)">></span> <span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)"> <table schema="" tableName="sys_user"></table> <table schema="" tableName="sys_role"></table> <table schema="" tableName="sys_permission"></table> <table schema="" tableName="sys_user_role"></table> <table schema="" tableName="sys_role_permission"></table> </span><span style="color: rgba(0, 128, 0, 1)">--></span> <span style="color: rgba(0, 128, 0, 1)"><!--</span><span style="color: rgba(0, 128, 0, 1)"> 有些表的字段需要指定java类型 <table schema="" tableName=""> <columnOverride column="" javaType="" /> </table> </span><span style="color: rgba(0, 128, 0, 1)">--></span> <span style="color: rgba(0, 0, 255, 1)"></</span><span style="color: rgba(128, 0, 0, 1)">context</span><span style="color: rgba(0, 0, 255, 1)">></span>
</generatorConfiguration>
3.3 使用 Java 类生成 mapper 文件
public class GeneratorSqlmap {</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> generator() <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> Exception{ List</span><String> warnings = <span style="color: rgba(0, 0, 255, 1)">new</span> ArrayList<String><span style="color: rgba(0, 0, 0, 1)">(); </span><span style="color: rgba(0, 0, 255, 1)">boolean</span> overwrite = <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">; </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">指定 逆向工程配置文件</span> File configFile = <span style="color: rgba(0, 0, 255, 1)">new</span> File("generatorConfig.xml"<span style="color: rgba(0, 0, 0, 1)">); ConfigurationParser cp </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ConfigurationParser(warnings); Configuration config </span>=<span style="color: rgba(0, 0, 0, 1)"> cp.parseConfiguration(configFile); DefaultShellCallback callback </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> DefaultShellCallback(overwrite); MyBatisGenerator myBatisGenerator </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> MyBatisGenerator(config, callback, warnings); myBatisGenerator.generate(</span><span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">); } </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> main(String[] args) <span style="color: rgba(0, 0, 255, 1)">throws</span><span style="color: rgba(0, 0, 0, 1)"> Exception { </span><span style="color: rgba(0, 0, 255, 1)">try</span><span style="color: rgba(0, 0, 0, 1)"> { GeneratorSqlmap generatorSqlmap </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> GeneratorSqlmap(); generatorSqlmap.generator(); } </span><span style="color: rgba(0, 0, 255, 1)">catch</span><span style="color: rgba(0, 0, 0, 1)"> (Exception e) { e.printStackTrace(); } }
}
生成后的代码:
3.4 拷贝生成的 mapper 文件到工程中指定的目录中
3.4.1mapper.xml
Mapper.xml 文件拷贝至 mapper 目录内
3.4.2mapper.java
Mapper.xml 文件拷贝至 mapper 目录内
注意:mapper.xml 文件和 mapper.java 文件在一个目录内且文件名相同。
3.4.3mapper 接口测试
public class ItemsMapperTest { private ApplicationContext applicationContext; private ItemsMapper itemsMapper;@Before </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> setUp(){ applicationContext</span>=<span style="color: rgba(0, 0, 255, 1)">new</span> ClassPathXmlApplicationContext("classpath:spring/applicationContext.xml"<span style="color: rgba(0, 0, 0, 1)">); itemsMapper</span>=(ItemsMapper) applicationContext.getBean("itemsMapper"<span style="color: rgba(0, 0, 0, 1)">); } @Test </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> testInsert() { Items item</span>=<span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Items(); item.setName(</span>"手机"<span style="color: rgba(0, 0, 0, 1)">); item.setPrice(999f);<br> item.setCreatetime(new Date()); itemsMapper.insert(item); } </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">自定义条件查询</span>
@Test
public void testSelectByExample() {
ItemsExample itemsExample=new ItemsExample();
//通过 criteria 构造查询条件
ItemsExample.Criteria criteria=itemsExample.createCriteria();
criteria.andNameEqualTo("笔记本 3");
//可能返回多条记录
List<Items> list=itemsMapper.selectByExample(itemsExample);
System.out.println(list);
}</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">根据主键查询</span>
@Test
public void testSelectByPrimaryKey() {
Items items=itemsMapper.selectByPrimaryKey(1);
System.out.println(items);
}@Test </span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> testUpdateByPrimaryKey() { </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">对所有字段进行更新,需要先查询出来再更新</span> Items items=itemsMapper.selectByPrimaryKey(1<span style="color: rgba(0, 0, 0, 1)">); items.setName(</span>"水杯"<span style="color: rgba(0, 0, 0, 1)">); itemsMapper.updateByPrimaryKey(items); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">如果传入字段不为空才更新,在批量更新中使用此方法,不需要先查询再更新</span>
itemsMapper.updateByPrimaryKeySelective(items);
}}
4. 逆向工程注意事项
4.1Mapper 文件内容不覆盖而是追加
XXXMapper.xml 文件已经存在时,如果进行重新生成则 mapper.xml 文件内容不被覆盖而是进行内容追加,结果导致 mybatis 解析失败。
解决方法:删除原来已经生成的 mapper.xml 文件再进行生成。
MyBatis 自动生成的 po 和 mapper.java 文件不是内容追加而是直接覆盖没有此问题。
4.2 Table schema 问题
下边是针对 Oracle 数据库表生成代码的 schema 问题:
schema 即数据库模式,oracle 中一个用户对应一个 schema, 可以理解为用户就是 schema。当 Oracle 数据库存在多个 Schema 可以访问相同的表名时,使用 mybatis 生成该表的 mapper.xml 将会出现 mapper 内容重复的问题,结果导致 mybatis 解析错误。
解决方法:在 table 中填写 schema, 如下:
<table schema="XXXX" tableName=" " >
XXXX 即为一个 schema 的名称,生成后将 mapper.xml 的 schema 前缀批量去掉,如果不去掉,当 Oracle 用户变更了 sql 语句将查询失败。
快捷操作方式:mapper.xml 文件中批量替换:“from XXXX.”为空。
Oracle 查询对象的 schema 可从 dba_objects 中查询,如下:
select * from dba_objects
如果此文对您有帮助,微信打赏我一下吧 ~