Mybatis generator 1.4.x 入门教程

一、前言

​ 最近因为公司开了新的项目,所以在构建骨架的时候发现mybatis最新的版本已经更新到了1.4.0了,尝试了一下,比起之前的mybatis版本,有了更好的优化,用上了lamada表达式,还支持动态sql查询,所以在这里安利一波,因为之前我用的Laravel ORM,所以比较习惯使用这种lamada表达式来查询,可能之前用习惯了以前的查询方式的

二、官方文档地址

官方文档地址

三、集成 mybatis Generator 1.4.0

pom文件

<!-- dependencies 依赖 -->
<dependencies>...<!-- 这里需要引入 动态sql相关的包--><!-- https://mvnrepository.com/artifact/org.mybatis.dynamic-sql/mybatis-dynamic-sql --><dependency><groupId>org.mybatis.dynamic-sql</groupId><artifactId>mybatis-dynamic-sql</artifactId><version>1.1.4</version></dependency>
</dependencies>     <!-- build 相关配置 -->
<build>
<plugins>
...
<!--mybatis自动生成代码--><plugin><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>1.4.0</version><dependencies></dependencies><configuration><!-- 这里设置配置文件的位置 --><configurationFile>src/main/resources/mybatis/configuration.xml</configurationFile><verbose>true</verbose><overwrite>true</overwrite></configuration></plugin>
</plugins>
</build>

配置文件 mybatis configuration.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">
<!--配置参考 http://mybatis.org/generator/configreference/xmlconfig.html-->
<generatorConfiguration><!-- 属性配置文件 --><properties resource="mybatis/db.properties"/><classPathEntry location="${jdbc.jar.path}"/><context id="testTables"defaultModelType="flat"><plugin type="org.mybatis.generator.plugins.SerializablePlugin"></plugin><commentGenerator><!-- 是否去除自动生成的注释 true:是 : false:否 --><property name="suppressAllComments" value="true"/></commentGenerator><!--数据库连接的信息:驱动类、连接地址、用户名、密码,这里配置的是mysql的,当然也可以配置oracle等数据库 --><jdbcConnection driverClass="${jdbc.driver}"connectionURL="${jdbc.url}"                                                        userId="${jdbc.username}" password="${jdbc.password}"></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.xxx.entity"       targetProject="src/main/java"><!-- enableSubPackages:是否让schema作为包的后缀 --><property name="enableSubPackages" value="true"/><!-- 从数据库返回的值被清理前后的空格 --><property name="trimStrings" value="true"/></javaModelGenerator><!-- targetPackage:mapper接口生成的位置 --><javaClientGenerator type="XMLMAPPER"                               targetPackage="com.xxx.mapper"targetProject="src/main/java"><!-- enableSubPackages:是否让schema作为包的后缀 --><property name="enableSubPackages" value="true"/></javaClientGenerator><!-- 指定数据库表 --><table tableName="xxx" schema="xxx"></table></context>
</generatorConfiguration>

配置属性文件 db.properties

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 查找

源码

// 根据provider查询多个记录@Generated("org.mybatis.generator.api.MyBatisGenerator")@SelectProvider(type=SqlProviderAdapter.class, method="select")@ResultMap("TeacherResult")Optional<Teacher> 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<Teacher> selectMany(SelectStatementProvider selectStatement);// 根据dsl 查询单个记录@Generated("org.mybatis.generator.api.MyBatisGenerator")default Optional<Teacher> selectOne(SelectDSLCompleter completer) {return MyBatis3Utils.selectOne(this::selectOne, selectList, teacher, completer);}
// 根据dsl 查询多个记录@Generated("org.mybatis.generator.api.MyBatisGenerator")default List<Teacher> select(SelectDSLCompleter completer) {return MyBatis3Utils.selectList(this::selectMany, selectList, teacher, completer);}@Generated("org.mybatis.generator.api.MyBatisGenerator")default List<Teacher> selectDistinct(SelectDSLCompleter completer) {return MyBatis3Utils.selectDistinct(this::selectMany, selectList, teacher, completer);}
// 根据主键查询记录@Generated("org.mybatis.generator.api.MyBatisGenerator")default Optional<Teacher> selectByPrimaryKey(Integer id_) {return selectOne(c ->c.where(id, isEqualTo(id_)));}

实例

    // 基本条件查询@Overridepublic Teacher findById(Integer teacherId) {Optional<Teacher> teacher = teacherMapper.selectOne(c ->c.where(TeacherDynamicSqlSupport.deleted, isEqualTo(false)).and(TeacherDynamicSqlSupport.id, isEqualTo(teacherId)));if (teacher.isPresent()){return teacher.get();}return null;}// 条件查询分页@Overridepublic List<Teacher> 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<Teacher> teachers = teacherMapper.selectMany(provider);return teachers;}

5.2 更新

源码

    // 根据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<UpdateModel> updateAllColumns(Teacher record, UpdateDSL<UpdateModel> 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<UpdateModel> updateSelectiveColumns(Teacher record, UpdateDSL<UpdateModel> 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)));}

实例

  @Overridepublic int update(Teacher teacher) {return teacherMapper.updateByPrimaryKeySelective(teacher);}

5.3 添加(插入)

源码

    // 直接完整插入@Generated("org.mybatis.generator.api.MyBatisGenerator")@InsertProvider(type=SqlProviderAdapter.class, method="insert")int insert(InsertStatementProvider<Teacher> insertStatement);@Generated("org.mybatis.generator.api.MyBatisGenerator")@InsertProvider(type=SqlProviderAdapter.class, method="insertMultiple")int insertMultiple(MultiRowInsertStatementProvider<Teacher> 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<Teacher> 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));}

实例

        @Overridepublic int create(Teacher teacher) {return teacherMapper.insertSelective(teacher);}

5.4 删除

源码

   @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

源码

 @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);}

实例

        // 这里比较坑的是select的参数是count,如果是其他的会报错@Overridepublic 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接口查询

@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<UserVO> selectManyJoin(SelectStatementProvider selectStatementProvider);

6.2 自定义sql解析器查询


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+)\\}\\)");@Overridepublic SqlSource createSqlSource(Configuration configuration, String script, Class<?> parameterType) {Matcher matcher = inPattern.matcher(script);if (matcher.find()) {script = matcher.replaceAll("<foreach collection=\"$1\" item=\"_item\" open=\"(\" "+ "separator=\",\" close=\")\" >#{_item}</foreach>");}script = "<script>" + script + "</script>";return super.createSqlSource(configuration, script, parameterType);}
}
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+)\\}\\)");@Overridepublic SqlSource createSqlSource(Configuration configuration, String script, Class<?> parameterType) {
//        Matcher matcher = inPattern.matcher(script);
//        if (matcher.find()) {
//            StringBuilder sb = new StringBuilder();
//            sb.append("<set>");
//
//            sb.append("<if test=\"name != null \">   name = #{name},</if>");
//            sb.append("<if test=\"price != null \"> price = #{price},</if>");/*   for (Field field : parameterType.getDeclaredFields()) {String tmp = "<if test=\"_field != null\">_column=#{_field},</if>";sb.append(tmp.replaceAll("_field", field.getName()).replaceAll("_column",CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, field.getName())));}*///            sb.deleteCharAt(sb.lastIndexOf(","));
//            sb.append("</set>");//            script = matcher.replaceAll(sb.toString());
//            script = "<script>" + script + "</script>";
//        }return super.createSqlSource(configuration, script, parameterType);}
}

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<UserBaseEntity> selectUserEntity();@Select("SELECT * FROM user_base  WHERE `name` NOT IN (SELECT name FROM user_base  WHERE id IN (#{idList}))")@Lang(SimpleSelectInLangDriver.class)List<UserBaseEntity> getUserByIdInBatch(@Param("idList") List<String> 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<String> userIds = ...
List<User> users = userMapper.select(c -> c.where(UserDynamicSqlSupport.id, isIn(userIds)));
  • bug

如果userIds 不为空(length = 0)的话,sql 语句是对的,如果userIds为空的话,sql语句就变成select * from user 了。÷

Mybatis generator 1.4.x 入门教程--转载相关推荐

  1. WPF入门教程-转载

    最近为了做炫酷的UI,了解了WPF,之前一直是使用winform的,界面也是古老的不行. 在园里找到了一个大佬以前写的教程,备注一下.按照系列教程走下来,可以直接上手了. 备忘传送门>>& ...

  2. TopCoder入门教程(转载)

    本文根据经典的TC教程完善和改编. TopCoder:http://www.topcoder.com/ 基本规则 TopCoder的比赛类型很多,最常见的是周赛SRM(Single Round Mat ...

  3. 【转载】PHP面向对象(OOP)编程入门教程

    面向对象编程(OOP)是我们编程的一项基本技能,PHP5对OOP提供了良好的支持. 如何使用OOP的思想来进行PHP的高级编程,对于提高 PHP编程能力和规划好Web开发构架都是非常有意义的.下面我们 ...

  4. TC(SRM)和CF入门教程for ACMer[转载]

    一.TC基本介绍TC的网址www.topcoder.com/tc,我们一般提到TC的时候是特指其中的Single Round Match(SRM).SRM的规则总结起来就是一句话:75分钟做完3道难度 ...

  5. 推荐 正则表达式入门教程

    看到编写比较好而且学习时间比较短的教程,很不错哦.推荐给大家学习. 正则表达式30分钟入门教程 转载于:https://blog.51cto.com/bearstudyhard/299713

  6. Arduino可穿戴开发入门教程Windows平台下安装Arduino IDE

    Arduino可穿戴开发入门教程Windows平台下安装Arduino IDE Windows平台下安装Arduino IDE Windows操作系统下可以使用安装向导和压缩包形式安装.下面详细讲解这 ...

  7. Arduino可穿戴开发入门教程Arduino开发环境介绍

    Arduino可穿戴开发入门教程Arduino开发环境介绍 Arduino开发环境介绍 Arduino不像我们使用的PC端操作系统一样,可以直接在操作系统中安装软件为操作系统编程.Arduino的软件 ...

  8. Arduino可穿戴开发入门教程LilyPad和LilyPad Simple的介绍

    Arduino可穿戴开发入门教程LilyPad和LilyPad Simple的介绍 LilyPad和LilyPad Simple的介绍 LilyPad和LilyPad Simple是LilyPad微控 ...

  9. Arduino可穿戴开发入门教程LilyPad介绍

    Arduino可穿戴开发入门教程LilyPad介绍 Arduino输出模块 LilyPad官方共提供了4种输出模块,他们分别是单色LED模块(图1.5).三色LED模块(图1.6).蜂鸣器模块(图1. ...

最新文章

  1. Scikit-learn 更新至 0.24 版,这 10 个新特性你需要了解
  2. Java并发基础02. 传统线程技术中的定时器技术
  3. 大亚DP607超级密码,破解方法
  4. [引]生成加密和解密的密钥
  5. 信佑无盘主服务器密码,(信佑无盘帮助手册.doc
  6. 复刻了一个史上最强 Redis 6.0 版本
  7. Java数据结构与算法(26) - ch12堆(堆实现)
  8. 一个老工程师的肺腑之言!!!
  9. WebStorm——cocos2d-html5专用IDE
  10. 机器学习笔记(六)数据分类
  11. 袋鼠云研发手记 | 袋鼠云EasyManager的TypeScript重构纪要...
  12. coding码市的运用
  13. 别太在意人走茶凉 物是人非
  14. nimble源码学习——广播流程源码分析1
  15. 解决Windows时间同步失败问题!系统时间同步设置!
  16. AJAX简单思维导图
  17. python语言的实验心得体会范文_实验心得体会范文
  18. Python将多张2D TIFF图片转为一个3D TIFF文件
  19. 北斗/GPS授时原理
  20. 2021/8/21错题

热门文章

  1. 寒冷的高纬度——我的梦开始的地方
  2. 1.4 消息循环和回调函数
  3. 网狐棋牌(四) TimerEngine
  4. sqlite的几个常用方法
  5. C++开发中的pImpl方法
  6. 什么是Flink?Flink能用来做什么?
  7. 音视频技术开发周刊 | 148
  8. 赵加雨:追求极致的习惯让我受益匪浅
  9. 从 bug 中学习:六大开源项目告诉你 go 并发编程的那些坑
  10. 《程序员歌单》请查收