热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

fluentmybatis学习一

FluentMybatis特性FluentMybatis原理创建一个示例的数据库表DROPTABLEIFEXISTSyour_table;createtableyour_tabl

  1. FluentMybatis特性
    在这里插入图片描述
  2. FluentMybatis原理
    在这里插入图片描述
  3. 创建一个示例的数据库表

DROP TABLE IF EXISTS `your_table`;create table `your_table`(id bigint auto_increment comment '主键ID' primary key,name varchar(30) charset utf8 null comment '姓名',age int null comment '年龄',email varchar(50) charset utf8 null comment '邮箱',gmt_create datetime null comment '记录创建时间',gmt_modified datetime null comment '记录最后修改时间',is_deleted tinyint(2) default 0 null comment '逻辑删除标识'
);

  1. 初始化 SpringBoot 项目
    spring boot: 基于spring boot开发,肯定是必须的
    lombok: 省略get, set, toString代码的神器,个人比较喜欢;你也可以手动生成get set方法
    mysql-connector-java: 数据库驱动
    fluent-mybatis: fluent-mybatis运行时依赖
    fluent-mybatis-processor: fluent-mybatis编译时依赖
    fluent-mybatis-generator: fluent-mybatis代码生成依赖
    测试依赖的jar包: spring-test, junit
  2. List item

spring.datasource.username=root
spring.datasource.password=password
spring.datasource.url=jdbc:mysql://localhost:3306/fluent_mybatis?useSSL=false&useUnicode=true&characterEncoding=utf-8
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

  1. 创建实体类 可以手工创建Entity类,或者任何手段创建的Entity类,然后加上下面注解
    在Entity类上加上 @FluentMybatis注解
    在主键字段加 @TableId注解
    在一般字段加 @TableField注解
    这里直接使用fluent mybatis提供的工具类生成代码

public class AppEntityGenerator {static final String url = "jdbc:mysql://localhost:3306/fluent_mybatis?useSSL=false&useUnicode=true&characterEncoding=utf-8";public static void main(String[] args) {FileGenerator.build(Abc.class);}@Tables(/** 数据库连接信息 **/url = url, username = "root", password = "password",/** Entity类parent package路径 **/basePack = "cn.org.fluent.mybatis.springboot.demo",/** Entity代码源目录 **/srcDir = "spring-boot-demo/src/main/java",/** Dao代码源目录 **/daoDir = "spring-boot-demo/src/main/java",/** 如果表定义记录创建,记录修改,逻辑删除字段 **/gmtCreated = "gmt_create", gmtModified = "gmt_modified", logicDeleted = "is_deleted",/** 需要生成文件的表 **/tables = @Table(value = {"your_table"}))static class Abc {}
}

  1. gmt_create, 记录创建时间,会设置记录插入的默认值,对应生成Entity字段上的注解 @TableField(insert=“now()”)
  2. gmt_modified, 记录最后更新时间,会设置记录插入和更新默认值,对应生成代码Entity字段上注解 @TableField(insert=“now()”, update=“now()”)
  3. is_deleted, 记录逻辑删除标识,字段类型为Boolean,且设置记录插入的默认值,对应注解 @TableField(insert=“0”)
  4. 执行生成代码main函数, 在工程main/src/java目录下产出 Entity, DaoIntf, DaoImpl文件; 观察YourEntity的主键 id, gmt_create, gmt_modified, is_deleted这几个字段的注解

@Data
@Accessors(chain = true)
@FluentMybatis(table = "your_table")
public class YourEntity implements IEntity{private static final long serialVersionUID = 1L;@TableId(value = "id")private Long id;@TableField(value = "gmt_create", insert = "now()")private Date gmtCreate;@TableField(value = "gmt_modified", insert = "now()", update = "now()")private Date gmtModified;@TableField(value = "is_deleted", insert = "0")private Boolean isDeleted;@TableField(value = "age")private Integer age;@TableField(value = "email")private String email;@TableField(value = "name")private String name;@Overridepublic Serializable findPk() {return id;}
}

  1. 生成的Dao文件,引用到了YourTableBaseDao类,这个类需要根据Entity类编译生成,在重新编译前会有编译错误,所以生成代码后需要重新Rebuild下

@Repository
public class YourDaoImpl extends YourBaseDao implements YourDao {// 在这里添加你自己的业务逻辑代码
}

  1. 启动SpringBoot测试,验证效果

@SpringBootTest(classes = QuickStartApplication.class)
public class FluentMybatisApplicationTest {&#64;Autowiredprivate YourMapper yourMapper;&#64;Testvoid contextLoads() {List<YourEntity> list &#61; yourMapper.listEntity(yourMapper.query());for (YourEntity entity : list) {System.out.println(entity);}}
}

  1. EntityMapper提供的insert操作

  2. insert->单条插入操作->Mapper方法

public interface YourMapper extends IEntityMapper<YourEntity> {/**1. 插入一条记录2. 3. &#64;param entity4. &#64;return*/&#64;Override&#64;InsertProvider(type &#61; YourSqlProvider.class,method &#61; "insert")&#64;Options(useGeneratedKeys &#61; true,keyProperty &#61; "id",keyColumn &#61; "id")int insert(YourEntity entity);
}

  1. 动态SQL组装

public class YourSqlProvider {public String insert(YourEntity entity) {assertNotNull("entity", entity);MapperSql sql &#61; new MapperSql();sql.INSERT_INTO("your_table");List<String> columns &#61; new ArrayList<>();List<String> values &#61; new ArrayList<>();if (entity.getId() !&#61; null) {columns.add("id");values.add("#{id}");}columns.add("gmt_create");if (entity.getGmtCreate() !&#61; null) {values.add("#{gmtCreate}");} else {values.add("now()");}columns.add("gmt_modified");if (entity.getGmtModified() !&#61; null) {values.add("#{gmtModified}");} else {values.add("now()");}columns.add("is_deleted");if (entity.getIsDeleted() !&#61; null) {values.add("#{isDeleted}");} else {values.add("0");}if (entity.getAge() !&#61; null) {columns.add("age");values.add("#{age}");}if (entity.getEmail() !&#61; null) {columns.add("email");values.add("#{email}");}if (entity.getName() !&#61; null) {columns.add("name");values.add("#{name}");}sql.INSERT_COLUMNS(columns);sql.VALUES();sql.INSERT_VALUES(values);return sql.toString();}
}

  1. 执行insert测试方法, 查看控制台输出log信息

DEBUG - &#61;&#61;> Preparing: INSERT INTO your_table(gmt_create, gmt_modified, is_deleted, age, email, name) VALUES (now(), now(), ?, ?, ?, ?)
DEBUG - &#61;&#61;> Parameters: false(Boolean), 1(Integer), darui.wu&#64;163.com(String), Fluent Mybatis(String)
DEBUG - <&#61;&#61; Updates: 1
count:1
entity:YourEntity(id&#61;18, gmtCreate&#61;null, gmtModified&#61;null, isDeleted&#61;false, age&#61;1, email&#61;darui.wu&#64;163.com, name&#61;Fluent Mybatis)

注意:


  1. Entity主键值的自增和回写 根据控制台输出&#xff0c;可以看到Entity的id属性已经是根据数据库自增主键值回写过的。 自增主键的设置是通过 &#64;TableId 注解来的&#xff0c;其属性方法auto()默认值是true。
  2. fluent mybatis根据&#64;TableId注解生成的Mapper类上&#64;Options注解如下&#xff1a;

&#64;Options(useGeneratedKeys &#61; true,keyProperty &#61; "id",keyColumn &#61; "id"
)

  1. gmt_created, gmt_modified, is_deleted 默认值插入处理 我们先看一下Entity上这3个字段的&#64;TableField注解, 他们都定义了一个属性方法insert&#xff0c;设置了insert的默认值&#xff08;即程序编码insert时&#xff0c;如果没有设置该字段&#xff0c;则使用默认值&#xff09;

&#64;TableField(value &#61; "gmt_create", insert &#61; "now()")private Date gmtCreate;&#64;TableField(value &#61; "gmt_modified", insert &#61; "now()", update &#61; "now()")private Date gmtModified;&#64;TableField(value &#61; "is_deleted", insert &#61; "0")private Boolean isDeleted;

  1. 在测试例子中&#xff0c;gmt_created和gmt_modified在初始化Entity时&#xff0c;没有设置任何值; is_deleted设置了值false。 在构建sql是&#xff0c;gmt_created, gmt_modified直接使用默认值 “now()”, is_deleted使用预编译变量(?)设置(实际值false)。

INSERT INTO your_table
(gmt_create, gmt_modified, is_deleted, age, email, name)
VALUES
(now(), now(), ?, ?, ?, ?)

  1. 我们再看一下对应的SQLProvider的SQL构造, 我们只看着3个字段的构造

public class YourSqlProvider {public String insert(YourEntity entity) {List<String> columns &#61; new ArrayList<>();List<String> values &#61; new ArrayList<>();// 省略 ... ...columns.add("gmt_create");if (entity.getGmtCreate() !&#61; null) {values.add("#{gmtCreate}");} else {values.add("now()");}columns.add("gmt_modified");if (entity.getGmtModified() !&#61; null) {values.add("#{gmtModified}");} else {values.add("now()");}columns.add("is_deleted");if (entity.getIsDeleted() !&#61; null) {values.add("#{isDeleted}");} else {values.add("0");}if (entity.getAge() !&#61; null) {columns.add("age");values.add("#{age}");}// 省略... ...return sql.toString();}
}

我们看到&#xff0c;没有 insert属性的字段&#xff0c;只判断了是否为空; 有insert属性的字段&#xff0c;如果entity不为空&#xff0c;则把默认值赋值给sql语句。

insertBatch 批量插入

public class YourSqlProvider {public String insertBatch(Map map) {assertNotEmpty("map", map);MapperSql sql &#61; new MapperSql();List<YourEntity> entities &#61; getParas(map, "list");sql.INSERT_INTO("your_table");sql.INSERT_COLUMNS(ALL_ENTITY_FIELDS);sql.VALUES();for (int index &#61; 0; index < entities.size(); index&#43;&#43;) {if (index > 0) {sql.APPEND(", ");}sql.INSERT_VALUES("#{list[" &#43; index &#43; "].id}",entities.get(index).getGmtCreate() &#61;&#61; null ? "now()" : "#{list[" &#43; index &#43; "].gmtCreate}",entities.get(index).getGmtModified() &#61;&#61; null ? "now()" : "#{list[" &#43; index &#43; "].gmtModified}",entities.get(index).getIsDeleted() &#61;&#61; null ? "0" : "#{list[" &#43; index &#43; "].isDeleted}","#{list[" &#43; index &#43; "].age}","#{list[" &#43; index &#43; "].email}","#{list[" &#43; index &#43; "].name}");}return sql.toString();}
}

SQL构造语句是通过一个for循环遍历实体列表&#xff0c;构造出下列SQL语句, 其中对有insert默认值属性处理方式同单条insert一样, 这里就不再重复。

NSERT INTO your_table (&#39;Entity对应的字段列表&#39;) VALUES (&#39;实例1值&#39;), (&#39;实例2值&#39;)

写个测试看看具体效果

&#64;SpringBootTest(classes &#61; QuickStartApplication.class)
public class FluentMybatisApplicationTest {&#64;Autowiredprivate YourMapper yourMapper;void insertBatch(){List<YourEntity> entities &#61; new ArrayList<>();entities.add(new YourEntity().setName("Fluent Mybatis").setEmail("darui.wu&#64;163.com"));entities.add(new YourEntity().setName("Fluent Mybatis Demo").setEmail("darui.wu&#64;163.com"));entities.add(new YourEntity().setName("Test4J").setEmail("darui.wu&#64;163.com"));int count &#61; yourMapper.insertBatch(entities);System.out.println("count:" &#43; count);System.out.println("entity:" &#43; entities);}
}

执行测试&#xff0c;查看控制台输出

DEBUG - &#61;&#61;> Preparing: INSERT INTO your_table(id, gmt_create, gmt_modified, is_deleted, age, email, name) VALUES (?, now(), now(), 0, ?, ?, ?) , (?, now(), now(), 0, ?, ?, ?) , (?, now(), now(), 0, ?, ?, ?)
DEBUG - &#61;&#61;> Parameters: null, null, darui.wu&#64;163.com(String), Fluent Mybatis(String), null, null, darui.wu&#64;163.com(String), Fluent Mybatis Demo(String), null, null, darui.wu&#64;163.com(String), Test4J(String)
DEBUG - <&#61;&#61; Updates: 3
count:3
entity:[YourEntity(id&#61;null, gmtCreate&#61;null, gmtModified&#61;null, isDeleted&#61;null, age&#61;null, email&#61;darui.wu&#64;163.com, name&#61;Fluent Mybatis), YourEntity(id&#61;null, gmtCreate&#61;null, gmtModified&#61;null, isDeleted&#61;null, age&#61;null, email&#61;darui.wu&#64;163.com, name&#61;Fluent Mybatis Demo), YourEntity(id&#61;null, gmtCreate&#61;null, gmtModified&#61;null, isDeleted&#61;null, age&#61;null, email&#61;darui.wu&#64;163.com, name&#61;Test4J)]

推荐阅读
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • SpringBoot uri统一权限管理的实现方法及步骤详解
    本文详细介绍了SpringBoot中实现uri统一权限管理的方法,包括表结构定义、自动统计URI并自动删除脏数据、程序启动加载等步骤。通过该方法可以提高系统的安全性,实现对系统任意接口的权限拦截验证。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • springmvc学习笔记(十):控制器业务方法中通过注解实现封装Javabean接收表单提交的数据
    本文介绍了在springmvc学习笔记系列的第十篇中,控制器的业务方法中如何通过注解实现封装Javabean来接收表单提交的数据。同时还讨论了当有多个注册表单且字段完全相同时,如何将其交给同一个控制器处理。 ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • 本文介绍了一种轻巧方便的工具——集算器,通过使用集算器可以将文本日志变成结构化数据,然后可以使用SQL式查询。集算器利用集算语言的优点,将日志内容结构化为数据表结构,SPL支持直接对结构化的文件进行SQL查询,不再需要安装配置第三方数据库软件。本文还详细介绍了具体的实施过程。 ... [详细]
  • 微信官方授权及获取OpenId的方法,服务器通过SpringBoot实现
    主要步骤:前端获取到code(wx.login),传入服务器服务器通过参数AppID和AppSecret访问官方接口,获取到OpenId ... [详细]
  • Java如何导入和导出Excel文件的方法和步骤详解
    本文详细介绍了在SpringBoot中使用Java导入和导出Excel文件的方法和步骤,包括添加操作Excel的依赖、自定义注解等。文章还提供了示例代码,并将代码上传至GitHub供访问。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • 本文探讨了C语言中指针的应用与价值,指针在C语言中具有灵活性和可变性,通过指针可以操作系统内存和控制外部I/O端口。文章介绍了指针变量和指针的指向变量的含义和用法,以及判断变量数据类型和指向变量或成员变量的类型的方法。还讨论了指针访问数组元素和下标法数组元素的等价关系,以及指针作为函数参数可以改变主调函数变量的值的特点。此外,文章还提到了指针在动态存储分配、链表创建和相关操作中的应用,以及类成员指针与外部变量的区分方法。通过本文的阐述,读者可以更好地理解和应用C语言中的指针。 ... [详细]
  • Week04面向对象设计与继承学习总结及作业要求
    本文总结了Week04面向对象设计与继承的重要知识点,包括对象、类、封装性、静态属性、静态方法、重载、继承和多态等。同时,还介绍了私有构造函数在类外部无法被调用、static不能访问非静态属性以及该类实例可以共享类里的static属性等内容。此外,还提到了作业要求,包括讲述一个在网上商城购物或在班级博客进行学习的故事,并使用Markdown的加粗标记和语句块标记标注关键名词和动词。最后,还提到了参考资料中关于UML类图如何绘制的范例。 ... [详细]
author-avatar
顺丰-03_457
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有