Mybatis generator 1.4.x 入门教程
一、前言
最近因为公司开了新的项目,所以在构建骨架的时候发现mybatis最新的版本已经更新到了1.4.0了,尝试了一下,比起之前的mybatis版本,有了更好的优化,用上了lamada表达式,还支持动态sql查询,所以在这里安利一波,因为之前我用的Laravel ORM,所以比较习惯使用这种lamada表达式来查询,可能之前用习惯了以前的查询方式的
二、官方文档地址
官方文档地址
三、集成 mybatis Generator 1.4.0
pom文件
代码语言:javascript复制 ...
org.mybatis.dynamic-sql
mybatis-dynamic-sql
1.1.4
...
org.mybatis.generator
mybatis-generator-maven-plugin
1.4.0
src/main/resources/mybatis/configuration.xml
true
true
配置文件 mybatis configuration.xml
代码语言:javascript复制
配置属性文件 db.properties
代码语言:javascript复制jdbc.jar.path=/Users/xxx/.m2/repository/mysql/mysql-connector-java/8.0.17/mysql-connector-java-8.0.17.jar
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://xxx:xxx:xxx:xxx:port/dbname?characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&verifyServerCertificate=false
jdbc.username=username
jdbc.password=password
...
四、执行generator生成 dao类和mapper接口
- 生成dao类中每个属性会自动加上@Generated
生成的dao类
- 生成的mapper接口类,会自动生成Mapper和DynamicSqlSupport
五、使用举例
- Dao实例
import java.io.Serializable;
import java.util.Date;
import javax.annotation.Generated;
public class Teacher implements Serializable {
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Integer id;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String teacherNumber;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String teacherName;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String telephone;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String email;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private String password;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Boolean deleted;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private Date createdTime;
@Generated("org.mybatis.gener"
"ator.api.MyBatisGenerator")
private Date updatedTime;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
private static final long serialVersionUID = 1L;
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public Integer getId() {
return id;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setId(Integer id) {
this.id = id;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public String getTeacherNumber() {
return teacherNumber;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setTeacherNumber(String teacherNumber) {
this.teacherNumber = teacherNumber == null ? null : teacherNumber.trim();
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public String getTeacherName() {
return teacherName;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setTeacherName(String teacherName) {
this.teacherName = teacherName == null ? null : teacherName.trim();
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public String getTelephone() {
return telephone;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setTelephone(String telephone) {
this.telephone = telephone == null ? null : telephone.trim();
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public String getEmail() {
return email;
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
public void setEmail(String email) {
this.email = email == null ? null : email.trim();
}
...
}
5.1 查找
源码
代码语言:javascript复制// 根据provider查询多个记录
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@SelectProvider(type=SqlProviderAdapter.class, method="select")
@ResultMap("TeacherResult")
Optional selectOne(SelectStatementProvider selectStatement);
// 根据provider查询多个记录
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@SelectProvider(type=SqlProviderAdapter.class, method="select")
@Results(id="TeacherResult", value = {
@Result(column="id", property="id", jdbcType=JdbcType.INTEGER, id=true),
@Result(column="teacher_number", property="teacherNumber", jdbcType=JdbcType.VARCHAR),
@Result(column="teacher_name", property="teacherName", jdbcType=JdbcType.VARCHAR),
@Result(column="telephone", property="telephone", jdbcType=JdbcType.VARCHAR),
@Result(column="email", property="email", jdbcType=JdbcType.VARCHAR),
@Result(column="password", property="password", jdbcType=JdbcType.VARCHAR),
@Result(column="deleted", property="deleted", jdbcType=JdbcType.BIT),
@Result(column="created_time", property="createdTime", jdbcType=JdbcType.TIMESTAMP),
@Result(column="updated_time", property="updatedTime", jdbcType=JdbcType.TIMESTAMP)
})
List selectMany(SelectStatementProvider selectStatement);
// 根据dsl 查询单个记录
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default Optional selectOne(SelectDSLCompleter completer) {
return MyBatis3Utils.selectOne(this::selectOne, selectList, teacher, completer);
}
// 根据dsl 查询多个记录
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default List select(SelectDSLCompleter completer) {
return MyBatis3Utils.selectList(this::selectMany, selectList, teacher, completer);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default List selectDistinct(SelectDSLCompleter completer) {
return MyBatis3Utils.selectDistinct(this::selectMany, selectList, teacher, completer);
}
// 根据主键查询记录
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default Optional selectByPrimaryKey(Integer id_) {
return selectOne(c ->
c.where(id, isEqualTo(id_))
);
}
实例
代码语言:javascript复制 // 基本条件查询
@Override
public Teacher findById(Integer teacherId) {
Optional teacher = teacherMapper.selectOne(c ->
c.where(TeacherDynamicSqlSupport.deleted, isEqualTo(false))
.and(TeacherDynamicSqlSupport.id, isEqualTo(teacherId))
);
if (teacher.isPresent()){
return teacher.get();
}
return null;
}
// 条件查询分页
@Override
public List getListByPager(TeacherSearchModel model) {
QueryExpressionWhereBuilder builder = select(TeacherDynamicSqlSupport.teacher.allColumns())
.from(TeacherDynamicSqlSupport.teacher)
.where(TeacherDynamicSqlSupport.deleted, isEqualTo(false));
if (!StringUtils.isEmpty(model.getNumberKeyWord()))
{
builder.and(TeacherDynamicSqlSupport.teacherNumber,isLike(model.getNumberKeyWord()));
}
if (!StringUtils.isEmpty(model.getNameKeyWord()))
{
builder.and(TeacherDynamicSqlSupport.teacherName,isLike(model.getNameKeyWord()));
}
builder.limit(model.getPageSize())
.offset(((model.getPageNumber()-1)*model.getPageSize()));
SelectStatementProvider provider = builder.build().render(RenderingStrategy.MYBATIS3);
List teachers = teacherMapper.selectMany(provider);
return teachers;
}
5.2 更新
源码
代码语言:javascript复制 // 根据provide更新
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@UpdateProvider(type=SqlProviderAdapter.class, method="update")
int update(UpdateStatementProvider updateStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int update(UpdateDSLCompleter completer) {
return MyBatis3Utils.update(this::update, teacher, completer);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
static UpdateDSL updateAllColumns(Teacher record, UpdateDSL dsl) {
return dsl.set(id).equalTo(record::getId)
.set(teacherNumber).equalTo(record::getTeacherNumber)
.set(teacherName).equalTo(record::getTeacherName)
.set(telephone).equalTo(record::getTelephone)
.set(email).equalTo(record::getEmail)
.set(password).equalTo(record::getPassword)
.set(deleted).equalTo(record::getDeleted)
.set(createdTime).equalTo(record::getCreatedTime)
.set(updatedTime).equalTo(record::getUpdatedTime);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
static UpdateDSL updateSelectiveColumns(Teacher record, UpdateDSL dsl) {
return dsl.set(id).equalToWhenPresent(record::getId)
.set(teacherNumber).equalToWhenPresent(record::getTeacherNumber)
.set(teacherName).equalToWhenPresent(record::getTeacherName)
.set(telephone).equalToWhenPresent(record::getTelephone)
.set(email).equalToWhenPresent(record::getEmail)
.set(password).equalToWhenPresent(record::getPassword)
.set(deleted).equalToWhenPresent(record::getDeleted)
.set(createdTime).equalToWhenPresent(record::getCreatedTime)
.set(updatedTime).equalToWhenPresent(record::getUpdatedTime);
}
// 通过主键更新数据
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int updateByPrimaryKey(Teacher record) {
return update(c ->
c.set(teacherNumber).equalTo(record::getTeacherNumber)
.set(teacherName).equalTo(record::getTeacherName)
.set(telephone).equalTo(record::getTelephone)
.set(email).equalTo(record::getEmail)
.set(password).equalTo(record::getPassword)
.set(deleted).equalTo(record::getDeleted)
.set(createdTime).equalTo(record::getCreatedTime)
.set(updatedTime).equalTo(record::getUpdatedTime)
.where(id, isEqualTo(record::getId))
);
}
// 通过主键条件更新数据
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int updateByPrimaryKeySelective(Teacher record) {
return update(c ->
c.set(teacherNumber).equalToWhenPresent(record::getTeacherNumber)
.set(teacherName).equalToWhenPresent(record::getTeacherName)
.set(telephone).equalToWhenPresent(record::getTelephone)
.set(email).equalToWhenPresent(record::getEmail)
.set(password).equalToWhenPresent(record::getPassword)
.set(deleted).equalToWhenPresent(record::getDeleted)
.set(createdTime).equalToWhenPresent(record::getCreatedTime)
.set(updatedTime).equalToWhenPresent(record::getUpdatedTime)
.where(id, isEqualTo(record::getId))
);
}
实例
代码语言:javascript复制 @Override
public int update(Teacher teacher) {
return teacherMapper.updateByPrimaryKeySelective(teacher);
}
5.3 添加(插入)
源码
代码语言:javascript复制 // 直接完整插入
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@InsertProvider(type=SqlProviderAdapter.class, method="insert")
int insert(InsertStatementProvider insertStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@InsertProvider(type=SqlProviderAdapter.class, method="insertMultiple")
int insertMultiple(MultiRowInsertStatementProvider multipleInsertStatement);
// 直接完整插入
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int insert(Teacher record) {
return MyBatis3Utils.insert(this::insert, record, teacher, c ->
c.map(id).toProperty("id")
.map(teacherNumber).toProperty("teacherNumber")
.map(teacherName).toProperty("teacherName")
.map(telephone).toProperty("telephone")
.map(email).toProperty("email")
.map(password).toProperty("password")
.map(deleted).toProperty("deleted")
.map(createdTime).toProperty("createdTime")
.map(updatedTime).toProperty("updatedTime")
);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int insertMultiple(Collection records) {
return MyBatis3Utils.insertMultiple(this::insertMultiple, records, teacher, c ->
c.map(id).toProperty("id")
.map(teacherNumber).toProperty("teacherNumber")
.map(teacherName).toProperty("teacherName")
.map(telephone).toProperty("telephone")
.map(email).toProperty("email")
.map(password).toProperty("password")
.map(deleted).toProperty("deleted")
.map(createdTime).toProperty("createdTime")
.map(updatedTime).toProperty("updatedTime")
);
}
// 条件部分插入
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int insertSelective(Teacher record) {
return MyBatis3Utils.insert(this::insert, record, teacher, c ->
c.map(id).toPropertyWhenPresent("id", record::getId)
.map(teacherNumber).toPropertyWhenPresent("teacherNumber", record::getTeacherNumber)
.map(teacherName).toPropertyWhenPresent("teacherName", record::getTeacherName)
.map(telephone).toPropertyWhenPresent("telephone", record::getTelephone)
.map(email).toPropertyWhenPresent("email", record::getEmail)
.map(password).toPropertyWhenPresent("password", record::getPassword)
.map(deleted).toPropertyWhenPresent("deleted", record::getDeleted)
.map(createdTime).toPropertyWhenPresent("createdTime", record::getCreatedTime)
.map(updatedTime).toPropertyWhenPresent("updatedTime", record::getUpdatedTime)
);
}
实例
代码语言:javascript复制 @Override
public int create(Teacher teacher) {
return teacherMapper.insertSelective(teacher);
}
5.4 删除
源码
代码语言:javascript复制 @Generated("org.mybatis.generator.api.MyBatisGenerator")
@DeleteProvider(type=SqlProviderAdapter.class, method="delete")
int delete(DeleteStatementProvider deleteStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int delete(DeleteDSLCompleter completer) {
return MyBatis3Utils.deleteFrom(this::delete, teacher, completer);
}
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default int deleteByPrimaryKey(Integer id_) {
return delete(c ->
c.where(id, isEqualTo(id_))
);
}
5.5 查询数量 Count
源码
代码语言:javascript复制 @Generated("org.mybatis.generator.api.MyBatisGenerator")
@SelectProvider(type=SqlProviderAdapter.class, method="select")
long count(SelectStatementProvider selectStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
@SelectProvider(type=SqlProviderAdapter.class, method="select")
long count(SelectStatementProvider selectStatement);
@Generated("org.mybatis.generator.api.MyBatisGenerator")
default long count(CountDSLCompleter completer) {
return MyBatis3Utils.countFrom(this::count, teacher, completer);
}
实例
代码语言:javascript复制 // 这里比较坑的是select的参数是count,如果是其他的会报错
@Override
public long getCountByModel(TeacherSearchModel model) {
QueryExpressionWhereBuilder builder = select(count()).
from(TeacherDynamicSqlSupport.teacher)
.where(TeacherDynamicSqlSupport.deleted, isEqualTo(false));
if (!StringUtils.isEmpty(model.getNumberKeyWord()))
{ builder.and(TeacherDynamicSqlSupport.teacherNumber,isLike(model.getNumberKeyWord()));
}
if (!StringUtils.isEmpty(model.getNameKeyWord()))
{
builder.and(TeacherDynamicSqlSupport.teacherName,isLike(model.getNameKeyWord()));
}
SelectStatementProvider provider = builder.build().render(RenderingStrategy.MYBATIS3);
long count = teacherMapper.count(provider);
return count;
}
5.6 查询条件
方法 | 说明 |
---|---|
isNull/isNotNull | 是否为空/不为空 |
isEqualTo/isNotEqualTo | 是否等于/不等于 |
isEqualToWhenPresent/isNotEqualToWhenPresent | 当存在时是否(不)等于 |
isGreaterThan/isGreaterThanWhenPresent | 大于 |
isGreaterThanOrEqualTo/isGreaterThanOrEqualToWhenPresent | 大于等于 |
isLessThan/isLessThanWhenPresent/ | 小于 |
isLessThanOrEqualTo/isLessThanOrEqualToWhenPresent | 小于等于 |
isIn/isNotIn | in操作 |
isInWhenPresent/isNotInWhenPresent | in操作 |
isBetween/isNotBetween | 是否在区间 |
isBetweenWhenPresent/isNotBetweenWhenPresent | 是否在区间 |
isLike/isNotLike | like(需要添加%) |
isLikeWhenPresent/isNotLikeWhenPresent | like(需要添加%) |
isTrue/isFalse | 是否是true/false |
isLikeCaseInsensitive/isLikeCaseInsensitiveWhenPresent | like(需要添加%) |
isNotLikeCaseInsensitive/isNotLikeCaseInsensitiveWhenPresent | like(需要添加%) |
isInCaseInsensitive/isInCaseInsensitiveWhenPresent | in操作 |
isNotInCaseInsensitive/isNotInCaseInsensitiveWhenPresent | in操作 |
六、自定义查询
6.1 自定义mapper接口查询
代码语言:javascript复制@Generated(value = "org.mybatis.generator.api.MyBatisGenerator",comments = "Source Table: user")
@SelectProvider(type = SqlProviderAdapter.class,method = "select")
@Results(id="UserVOResult", value = {
@Result(column="id", property="id", jdbcType= JdbcType.VARCHAR, id=true),
@Result(column="user_name", property="userName", jdbcType=JdbcType.VARCHAR),
@Result(column="gender", property="gender", jdbcType=JdbcType.BIT),
@Result(column="avatar", property="avatar", jdbcType=JdbcType.VARCHAR),
@Result(column="mobile", property="mobile", jdbcType=JdbcType.VARCHAR),
@Result(column="email", property="email", jdbcType=JdbcType.VARCHAR),
@Result(column="organization_name", property="organizationName", jdbcType=JdbcType.VARCHAR),
@Result(column="real_name", property="realName", jdbcType=JdbcType.VARCHAR),
@Result(column="main_organization", property="mainOrganization", jdbcType=JdbcType.INTEGER),
@Result(column="organization", property="organization", jdbcType=JdbcType.VARCHAR),
@Result(column="create_time", property="createTime", jdbcType=JdbcType.TIMESTAMP),
@Result(column="update_time", property="updateTime", jdbcType=JdbcType.TIMESTAMP)
})
List selectManyJoin(SelectStatementProvider selectStatementProvider);
6.2 自定义sql解析器查询
代码语言:javascript复制import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.ibatis.mapping.SqlSource;
import org.apache.ibatis.scripting.LanguageDriver;
import org.apache.ibatis.scripting.xmltags.XMLLanguageDriver;
import org.apache.ibatis.session.Configuration;
/**
* 解析sql语句该类主要用作select
*/
public class SimpleSelectInLangDriver extends XMLLanguageDriver implements LanguageDriver {
private static final Pattern inPattern = Pattern.compile("\(#\{(\w )\}\)");
@Override
public SqlSource createSqlSource(Configuration configuration, String script, Class parameterType) {
Matcher matcher = inPattern.matcher(script);
if (matcher.find()) {
script = matcher.replaceAll("#{_item}");
}
script = "" script "";
return super.createSqlSource(configuration, script, parameterType);
}
}
代码语言:javascript复制import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.ibatis.mapping.SqlSource;
import org.apache.ibatis.scripting.LanguageDriver;
import org.apache.ibatis.scripting.xmltags.XMLLanguageDriver;
import org.apache.ibatis.session.Configuration;
/**
* 解析sql语句
*/
public class SimpleUpdateLangDriver extends XMLLanguageDriver implements LanguageDriver{
private final Pattern inPattern = Pattern.compile("\(#\{(\w )\}\)");
@Override
public SqlSource createSqlSource(Configuration configuration, String script, Class parameterType) {
// Matcher matcher = inPattern.matcher(script);
// if (matcher.find()) {
// StringBuilder sb = new StringBuilder();
// sb.append("");
//
// sb.append(" name = #{name},");
// sb.append(" price = #{price},");
/* for (Field field : parameterType.getDeclaredFields()) {
String tmp = "_column=#{_field},";
sb.append(tmp.replaceAll("_field", field.getName()).replaceAll("_column",
CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, field.getName())));
}*/
// sb.deleteCharAt(sb.lastIndexOf(","));
// sb.append("");
// script = matcher.replaceAll(sb.toString());
// script = "" script "";
// }
return super.createSqlSource(configuration, script, parameterType);
}
}
代码语言:javascript复制import cn.jhunicom.visitor.miniapp.model.entity.mysql.UserBaseEntity;
import cn.jhunicom.visitor.miniapp.utils.SimpleSelectInLangDriver;
import cn.jhunicom.visitor.miniapp.utils.SimpleUpdateLangDriver;
import org.apache.ibatis.annotations.Lang;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import java.util.List;
public interface UserBaseEntityMapperExt extends UserBaseEntityMapper {
@Select("SELECT * FROM user_base")
@Lang(SimpleSelectInLangDriver.class)
List selectUserEntity();
@Select("SELECT * FROM user_base WHERE `name` NOT IN (SELECT name FROM user_base WHERE id IN (#{idList}))")
@Lang(SimpleSelectInLangDriver.class)
List getUserByIdInBatch(@Param("idList") List idList);
@Update("UPDATE user_base set name = #{name} WHERE id = #{id}")
@Lang(SimpleUpdateLangDriver.class)
void updateUsersById(UserBaseEntity userBaseEntity);
}
七、bug记录
7.1 in操作的坑
isIn/isNotIn/isInCaseInsensitive/isInCaseInsensitiveWhenPresent/isNotInCaseInsensitive/isNotInCaseInsensitiveWhenPresent 操作中,如果给的List(获取其他可迭代对象)为空的话,这个条件就不生效了。
- 例如你要进行如下操作
select * from user where id in ("xxx","xxx")
- mybatis 中写法
List userIds = ...
List users = userMapper.select(c -> c.where(UserDynamicSqlSupport.id, isIn(userIds)));
- bug
如果userIds 不为空(length = 0)的话,sql 语句是对的,如果userIds为空的话,sql语句就变成
select * from user
了。÷