一. MyBatis 逆向工程
MyBatis 逆向工程,存放于github, 就是通过数据库表,来自动生成 POJO 实体类和 mapper 中的XxxMapper.java 和XxxMapper.xml 配置文件,只能对单表进行相应的操作,暂时不能生成关联表的映射。 老蝴蝶本文所用的是 1.3.2 版本。
解压之后:
其中,lib包下有:
以mybatis数据库表下的四个表为例。 前面讲关联关系时所用到的表。
为了避免出现文件覆盖,最好是将自动生成代码的逆向工程单纯创建一个项目,然后copy 自动生成的文件到mybatis 项目中。
二. MyBatis 的逆向工程
二.一 创建逆向工程项目 MyBatis_Generator,避免出现文件覆盖。
二.二 创建lib文件夹,放入jar包。
二.三 在mybatis_generator项目下放置generatorConfig.xml 配置文件
注意,放置在整个项目下,与src 同级,并不是放置在src目录下。
二.四 在generator包下创建 GeneratorSqlmap.java 类来自动生成代码
package generator;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
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;
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();
}
}
}
二.五 创建好逆向工程的整个目录结构
二.六 generatorConfig.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="mybatisTest" targetRuntime="MyBatis3">
<commentGenerator>
<!-- 是否去除自动生成的注释 true:是 : false:否 -->
<property name="suppressAllComments" value="true" />
<!--去除日期注释-->
<property name="suppressDate" value="true"/>
</commentGenerator>
<!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
<jdbcConnection driverClass="com.mysql.jdbc.Driver"
connectionURL="jdbc:mysql://localhost:3306/mybatis" userId="root"
password="abc123">
</jdbcConnection>
<!-- 关于oracle的数据库连接信息 -->
<!-- <jdbcConnection driverClass="oracle.jdbc.OracleDriver"
connectionURL="jdbc:oracle:thin:@127.0.0.1:1521:orcl"
userId="scott"
password="abc123">
</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.yjl.pojo"
targetProject=".\src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
<!-- 从数据库返回的值被清理前后的空格 -->
<property name="trimStrings" value="true" />
</javaModelGenerator>
<!-- targetProject:mapper映射文件生成的位置 -->
<sqlMapGenerator targetPackage="com.yjl.mapper"
targetProject=".\src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
</sqlMapGenerator>
<!-- targetPackage:mapper接口生成的位置 -->
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.yjl.mapper"
targetProject=".\src">
<!-- enableSubPackages:是否让schema作为包的后缀 -->
<property name="enableSubPackages" value="false" />
</javaClientGenerator>
<!-- 指定数据库表,哪些单表-->
<table tableName="user"></table>
<table tableName="dept"></table>
<table tableName="role"></table>
<table tableName="idcard"></table>
<!-- 有些表的字段需要指定java类型
<table schema="" tableName="">
<columnOverride column="" javaType="" />
</table> -->
</context>
</generatorConfiguration>
其中,关于generatorConfig.xml 配置文件详细解释,可以参考 :javascript:void(0) (不知道这位前辈的转载原处地址,所以无法贴出正确的原始地址,还请理解)。
二.七 运行GeneratorSqlmap 类,看控制台输出。
老蝴蝶的输出是: 其中column 为那些表下的列名。 根据不同的表,会有不同的输出情况。
2019-07-16 19:24:08,106 [main] DEBUG [org.mybatis.generator.internal.db.DatabaseIntrospector] - Retrieving column information for table "user"
2019-07-16 19:24:08,122 [main] DEBUG [org.mybatis.generator.internal.db.DatabaseIntrospector] - Found column "id", data type 4, in table "mybatis..user"
2019-07-16 19:24:08,122 [main] DEBUG [org.mybatis.generator.internal.db.DatabaseIntrospector] - Found column "name", data type 12, in table "mybatis..user"
2019-07-16 19:24:08,122 [main] DEBUG [org.mybatis.generator.internal.db.DatabaseIntrospector] - Found column "age", data type 4, in table "mybatis..user"
2019-07-16 19:24:08,123 [main] DEBUG [org.mybatis.generator.internal.db.DatabaseIntrospector] - Found column "sex", data type 12, in table "mybatis..user"
2019-07-16 19:24:08,123 [main] DEBUG [org.mybatis.generator.internal.db.DatabaseIntrospector] - Found column "description", data type 12, in table "mybatis..user"
2019-07-16 19:24:08,125 [main] DEBUG [org.mybatis.generator.internal.db.DatabaseIntrospector] - Retrieving column information for table "dept"
2019-07-16 19:24:08,128 [main] DEBUG [org.mybatis.generator.internal.db.DatabaseIntrospector] - Found column "id", data type 4, in table "mybatis..dept"
2019-07-16 19:24:08,128 [main] DEBUG [org.mybatis.generator.internal.db.DatabaseIntrospector] - Found column "name", data type 12, in table "mybatis..dept"
2019-07-16 19:24:08,128 [main] DEBUG [org.mybatis.generator.internal.db.DatabaseIntrospector] - Found column "description", data type 12, in table "mybatis..dept"
2019-07-16 19:24:08,130 [main] DEBUG [org.mybatis.generator.internal.db.DatabaseIntrospector] - Retrieving column information for table "role"
2019-07-16 19:24:08,133 [main] DEBUG [org.mybatis.generator.internal.db.DatabaseIntrospector] - Found column "id", data type 4, in table "mybatis..role"
2019-07-16 19:24:08,133 [main] DEBUG [org.mybatis.generator.internal.db.DatabaseIntrospector] - Found column "name", data type 12, in table "mybatis..role"
2019-07-16 19:24:08,133 [main] DEBUG [org.mybatis.generator.internal.db.DatabaseIntrospector] - Retrieving column information for table "idcard"
2019-07-16 19:24:08,137 [main] DEBUG [org.mybatis.generator.internal.db.DatabaseIntrospector] - Found column "id", data type 4, in table "mybatis..idcard"
2019-07-16 19:24:08,137 [main] DEBUG [org.mybatis.generator.internal.db.DatabaseIntrospector] - Found column "idnum", data type 12, in table "mybatis..idcard"
刷新项目,F5, 便可以观察到自动生成的代码。
将 mapper 和pojo 包下 copy 到MyBatis 项目中即可。
三. 自动生成的代码解析
三.一 POJO 类
1.pojo 类会根据表名(首字母大写) 创建相应的类名。 如user—>变成了User.java 类。
2. 会将user 表中的column 类名 变成类中的属性,默认为包装类型,并且创建setter和getter方法。
3. setter方法,如果在generatorConfig.xml 设置了
那么 setter 方法为:
public void setName(String name) {
this.name = name == null ? null : name.trim();
}
<!-- 定义表的resultMap, 并且指定属性的jdbcType -->
<resultMap id="BaseResultMap" type="com.yjl.pojo.User" >
<id column="id" property="id" jdbcType="INTEGER" />
<result column="name" property="name" jdbcType="VARCHAR" />
<result column="age" property="age" jdbcType="INTEGER" />
<result column="sex" property="sex" jdbcType="VARCHAR" />
<result column="description" property="description" jdbcType="VARCHAR" />
</resultMap>
2 . 定义查询条件的sql片段,用于拼接 where 后的查询条件。
<!--拼接 查询时所用的sql片段-->
<sql id="Example_Where_Clause" >
<where >
<foreach collection="oredCriteria" item="criteria" separator="or" >
<if test="criteria.valid" >
<trim prefix="(" suffix=")" prefixOverrides="and" >
<foreach collection="criteria.criteria" item="criterion" >
<choose >
<when test="criterion.noValue" >
and ${criterion.condition}
</when>
<when test="criterion.singleValue" >
and ${criterion.condition} #{criterion.value}
</when>
<when test="criterion.betweenValue" >
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
</when>
<when test="criterion.listValue" >
and ${criterion.condition}
<foreach collection="criterion.value" item="listItem" open="(" close=")" separator="," >
#{listItem}
</foreach>
</when>
</choose>
</foreach>
</trim>
</if>
</foreach>
</where>
</sql>
3 . 定义更新条件的sql 片段,用于拼接 where 后的更新条件。
<!--定义更新时,所用的sql片段-->
<sql id="Update_By_Example_Where_Clause" >
<where >
<foreach collection="example.oredCriteria" item="criteria" separator="or" >
<if test="criteria.valid" >
<trim prefix="(" suffix=")" prefixOverrides="and" >
<foreach collection="criteria.criteria" item="criterion" >
<choose >
<when test="criterion.noValue" >
and ${criterion.condition}
</when>
<when test="criterion.singleValue" >
and ${criterion.condition} #{criterion.value}
</when>
<when test="criterion.betweenValue" >
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
</when>
<when test="criterion.listValue" >
and ${criterion.condition}
<foreach collection="criterion.value" item="listItem" open="(" close=")" separator="," >
#{listItem}
</foreach>
</when>
</choose>
</foreach>
</trim>
</if>
</foreach>
</where>
</sql>
4 . 定义基本的列片段,方便查询使用。
<!-- 定义 基本的列片段,方便查询使用 -->
<sql id="Base_Column_List" >
id, name, age, sex, description
</sql>
接下来,就是具体的查询方法了。
5 . selectByExample
<select id="selectByExample" resultMap="BaseResultMap" parameterType="com.yjl.pojo.UserExample" >
select
<!-- 看是否去重,为boolean 值 -->
<if test="distinct" >
distinct
</if>
<include refid="Base_Column_List" />
from user
<if test="_parameter != null" >
<include refid="Example_Where_Clause" />
</if>
<!-- 有值,就进行排序,拼接排序后的字段 -->
<if test="orderByClause != null" >
order by ${orderByClause}
</if>
</select>
6 . selectByPrimaryKey
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
select
<include refid="Base_Column_List" />
from user
where id = #{id,jdbcType=INTEGER}
</select>
7 . deleteByPrimaryKey
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" >
delete from user
where id = #{id,jdbcType=INTEGER}
</delete>
8 . deleteByExample
<delete id="deleteByExample" parameterType="com.yjl.pojo.UserExample" >
delete from user
<if test="_parameter != null" >
<include refid="Example_Where_Clause" />
</if>
</delete>
9 . insert 插入全部的字段
<insert id="insert" parameterType="com.yjl.pojo.User" >
insert into user (id, name, age,
sex, description)
values (#{id,jdbcType=INTEGER}, #{name,jdbcType=VARCHAR}, #{age,jdbcType=INTEGER},
#{sex,jdbcType=VARCHAR}, #{description,jdbcType=VARCHAR})
</insert>
10 . insertSelective
<insert id="insertSelective" parameterType="com.yjl.pojo.User" >
insert into user
<!--有选择性的拼接属性-->
<trim prefix="(" suffix=")" suffixOverrides="," >
<if test="id != null" >
id,
</if>
<if test="name != null" >
name,
</if>
<if test="age != null" >
age,
</if>
<if test="sex != null" >
sex,
</if>
<if test="description != null" >
description,
</if>
</trim>
<!--拼接value后半部分-->
<trim prefix="values (" suffix=")" suffixOverrides="," >
<if test="id != null" >
#{id,jdbcType=INTEGER},
</if>
<if test="name != null" >
#{name,jdbcType=VARCHAR},
</if>
<if test="age != null" >
#{age,jdbcType=INTEGER},
</if>
<if test="sex != null" >
#{sex,jdbcType=VARCHAR},
</if>
<if test="description != null" >
#{description,jdbcType=VARCHAR},
</if>
</trim>
</insert>
11 . countByExample
<select id="countByExample" parameterType="com.yjl.pojo.UserExample" resultType="java.lang.Integer" >
select count(*) from user
<if test="_parameter != null" >
<include refid="Example_Where_Clause" />
</if>
</select>
12 . updateByExampleSelective
<update id="updateByExampleSelective" parameterType="map" >
update user
<set >
<!-- 有,才进行更新 -->
<if test="record.id != null" >
id = #{record.id,jdbcType=INTEGER},
</if>
<if test="record.name != null" >
name = #{record.name,jdbcType=VARCHAR},
</if>
<if test="record.age != null" >
age = #{record.age,jdbcType=INTEGER},
</if>
<if test="record.sex != null" >
sex = #{record.sex,jdbcType=VARCHAR},
</if>
<if test="record.description != null" >
description = #{record.description,jdbcType=VARCHAR},
</if>
</set>
<!--拼接更新 where 语句-->
<if test="_parameter != null" >
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
13 . updateByExample
<update id="updateByExample" parameterType="map" >
update user
set id = #{record.id,jdbcType=INTEGER},
name = #{record.name,jdbcType=VARCHAR},
age = #{record.age,jdbcType=INTEGER},
sex = #{record.sex,jdbcType=VARCHAR},
description = #{record.description,jdbcType=VARCHAR}
<if test="_parameter != null" >
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
14 . updateByPrimaryKeySelective
<update id="updateByPrimaryKeySelective" parameterType="com.yjl.pojo.User" >
update user
<set >
<if test="name != null" >
name = #{name,jdbcType=VARCHAR},
</if>
<if test="age != null" >
age = #{age,jdbcType=INTEGER},
</if>
<if test="sex != null" >
sex = #{sex,jdbcType=VARCHAR},
</if>
<if test="description != null" >
description = #{description,jdbcType=VARCHAR},
</if>
</set>
where id = #{id,jdbcType=INTEGER}
</update>
15 . updateByPrimaryKey
<update id="updateByPrimaryKey" parameterType="com.yjl.pojo.User" >
update user
set name = #{name,jdbcType=VARCHAR},
age = #{age,jdbcType=INTEGER},
sex = #{sex,jdbcType=VARCHAR},
description = #{description,jdbcType=VARCHAR}
where id = #{id,jdbcType=INTEGER}
</update>
这就是XxxMapper.xml 自动生成的主要代码。
四. 测试
四.一 insert() 方法的测试
@Test
public void insertF1Test(){
SqlSession sqlSession=SqlSessionFactoryUtils.getSession();
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
User user=new User();
//不设置id,就报id为null的错误。 必须手动填写id
user.setId(7);
user.setName("自动生成插入名称");
user.setSex("自动生成插入性别");
user.setAge(24);
user.setDescription("自动生成插入描述");
userMapper.insert(user);
sqlSession.commit();
System.out.println(user);
}
四.二 insertSelective() 方法的测试
@Test
public void insertF2Test(){
SqlSession sqlSession=SqlSessionFactoryUtils.getSession();
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
User user=new User();
user.setName("自动生成插入名称");
user.setSex("自动生成插入性别");
user.setAge(24);
user.setDescription("自动生成插入描述");
int result=userMapper.insertSelective(user);
sqlSession.commit();
//可以自动生成,但不会返回id .
System.out.println(user); //并不会打印出user中 id的值,不会回显。
System.out.println("输出插入后的id:"+result); //1
}
四.三 updateByPrimaryKey() 方法的测试
@Test
public void updateF1Test(){
SqlSession sqlSession=SqlSessionFactoryUtils.getSession();
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
User user=new User();
user.setId(8);
user.setName("自动修改插入名称");
user.setSex("自动修改插入性别");
user.setDescription("自动生成插入描述");
userMapper.updateByPrimaryKey(user);
sqlSession.commit();
System.out.println(user);
}
四.四 updateByPrimaryKeySelective() 方法的测试
@Test
public void updateF2Test(){
SqlSession sqlSession=SqlSessionFactoryUtils.getSession();
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
User user=new User();
user.setId(8);
user.setName("自动修改插入名称");
user.setSex("自动修改插入性别123");
userMapper.updateByPrimaryKeySelective(user);
sqlSession.commit();
//可以自动生成,但不会返回id .
System.out.println(user);
}
四.五 updateByExampleSelective() 方法的测试
@Test
public void updateF3Test(){
SqlSession sqlSession=SqlSessionFactoryUtils.getSession();
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
User user=new User();
user.setId(8);
user.setName("自动条件插入名称");
user.setSex("自动条件插入性别123");
user.setAge(26);
UserExample example=new UserExample();
Criteria criteria=example.createCriteria();
criteria.andIdEqualTo(8);
criteria.andAgeIsNull();
userMapper.updateByExampleSelective(user,example);
sqlSession.commit();
//可以自动生成,但不会返回id .
System.out.println(user);
}
四.六 updateByExample() 方法的测试
@Test
public void updateF4Test(){
SqlSession sqlSession=SqlSessionFactoryUtils.getSession();
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
User user=new User();
user.setId(8);
user.setName("自动条件插入名称");
user.setAge(26);
UserExample example=new UserExample();
Criteria criteria=example.createCriteria();
criteria.andIdEqualTo(8);
criteria.andAgeIsNull();
userMapper.updateByExample(user,example);
sqlSession.commit();
//可以自动生成,但不会返回id .
System.out.println(user);
}
四.七 countByExample() 方法的测试
@Test
public void countByExampleTest(){
SqlSession sqlSession=SqlSessionFactoryUtils.getSession();
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
UserExample example=new UserExample();
Criteria criteria=example.createCriteria();
criteria.andAgeEqualTo(24);
criteria.andSexEqualTo("男");
int count=userMapper.countByExample(example);
System.out.println("数目是:"+count);
}
四.八 selectByExample() 方法的测试
@Test
public void selectByExampleTest(){
SqlSession sqlSession=SqlSessionFactoryUtils.getSession();
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
UserExample example=new UserExample();
Criteria criteria=example.createCriteria();
criteria.andAgeEqualTo(24);
criteria.andSexEqualTo("男");
List<User> userList=userMapper.selectByExample(example);
userList.forEach(n ->System.out.println(n));
}
四。九 deleteByExample() 方法的测试
@Test
public void deleteTest(){
SqlSession sqlSession=SqlSessionFactoryUtils.getSession();
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
UserExample example=new UserExample();
Criteria criteria=example.createCriteria();
criteria.andIdEqualTo(8);
criteria.andAgeIsNull();
userMapper.deleteByExample(example);
sqlSession.commit();
}
其他的方法与其类似,就不讲述了。
谢谢!!!