fluent-mybatis学习一

  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;

    @Override
    public 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 {
    @Autowired
    private YourMapper yourMapper;

    @Test
    void contextLoads() {
        List<YourEntity> list = 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. @param entity
 4. @return
   */
  @Override
  @InsertProvider(
      type = YourSqlProvider.class,
      method = "insert"
  )
  @Options(
      useGeneratedKeys = true,
      keyProperty = "id",
      keyColumn = "id"
  )
  int insert(YourEntity entity);
}
  1. 动态SQL组装
public class YourSqlProvider {
    public String insert(YourEntity entity) {
        assertNotNull("entity", entity);
        MapperSql sql = new MapperSql();
        sql.INSERT_INTO("your_table");
        List<String> columns = new ArrayList<>();
        List<String> values = new ArrayList<>();
        if (entity.getId() != null) {
            columns.add("id");
            values.add("#{id}");
        }
        columns.add("gmt_create");
        if (entity.getGmtCreate() != null) {
            values.add("#{gmtCreate}");
        } else {
            values.add("now()");
        }
        columns.add("gmt_modified");
        if (entity.getGmtModified() != null) {
            values.add("#{gmtModified}");
        } else {
            values.add("now()");
        }
        columns.add("is_deleted");
        if (entity.getIsDeleted() != null) {
            values.add("#{isDeleted}");
        } else {
            values.add("0");
        }
        if (entity.getAge() != null) {
            columns.add("age");
            values.add("#{age}");
        }
        if (entity.getEmail() != null) {
            columns.add("email");
            values.add("#{email}");
        }
        if (entity.getName() != null) {
            columns.add("name");
            values.add("#{name}");
        }
        sql.INSERT_COLUMNS(columns);
        sql.VALUES();
        sql.INSERT_VALUES(values);
        return sql.toString();
    }
}
  1. 执行insert测试方法, 查看控制台输出log信息
DEBUG - ==>  Preparing: INSERT INTO your_table(gmt_create, gmt_modified, is_deleted, age, email, name) VALUES (now(), now(), ?, ?, ?, ?)  
DEBUG - ==> Parameters: false(Boolean), 1(Integer), darui.wu@163.com(String), Fluent Mybatis(String) 
DEBUG - <==    Updates: 1 
count:1
entity:YourEntity(id=18, gmtCreate=null, gmtModified=null, isDeleted=false, age=1, email=darui.wu@163.com, name=Fluent Mybatis)

注意:

  1. Entity主键值的自增和回写 根据控制台输出,可以看到Entity的id属性已经是根据数据库自增主键值回写过的。 自增主键的设置是通过 @TableId 注解来的,其属性方法auto()默认值是true。
  2. fluent mybatis根据@TableId注解生成的Mapper类上@Options注解如下:
@Options(
  useGeneratedKeys = true,
  keyProperty = "id",
  keyColumn = "id"
)
  1. gmt_created, gmt_modified, is_deleted 默认值插入处理 我们先看一下Entity上这3个字段的@TableField注解, 他们都定义了一个属性方法insert,设置了insert的默认值(即程序编码insert时,如果没有设置该字段,则使用默认值)
 @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;
  1. 在测试例子中,gmt_created和gmt_modified在初始化Entity时,没有设置任何值; is_deleted设置了值false。 在构建sql是,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 = new ArrayList<>();
        List<String> values = new ArrayList<>();
        // 省略 ... ...
        columns.add("gmt_create");
        if (entity.getGmtCreate() != null) {
            values.add("#{gmtCreate}");
        } else {
            values.add("now()");
        }
        columns.add("gmt_modified");
        if (entity.getGmtModified() != null) {
            values.add("#{gmtModified}");
        } else {
            values.add("now()");
        }
        columns.add("is_deleted");
        if (entity.getIsDeleted() != null) {
            values.add("#{isDeleted}");
        } else {
            values.add("0");
        }
        if (entity.getAge() != null) {
            columns.add("age");
            values.add("#{age}");
        }
        // 省略... ...
        return sql.toString();
    }
}
我们看到,没有 insert属性的字段,只判断了是否为空; 有insert属性的字段,如果entity不为空,则把默认值赋值给sql语句。
insertBatch 批量插入
public class YourSqlProvider {
    public String insertBatch(Map map) {
        assertNotEmpty("map", map);
        MapperSql sql = new MapperSql();
        List<YourEntity> entities = getParas(map, "list");
        sql.INSERT_INTO("your_table");
        sql.INSERT_COLUMNS(ALL_ENTITY_FIELDS);
        sql.VALUES();
        for (int index = 0; index < entities.size(); index++) {
            if (index > 0) {
                sql.APPEND(", ");
            }
            sql.INSERT_VALUES(
                "#{list[" + index + "].id}",
                entities.get(index).getGmtCreate() == null ? "now()" : "#{list[" + index + "].gmtCreate}",
                entities.get(index).getGmtModified() == null ? "now()" : "#{list[" + index + "].gmtModified}",
                entities.get(index).getIsDeleted() == null ? "0" : "#{list[" + index + "].isDeleted}",
                "#{list[" + index + "].age}",
                "#{list[" + index + "].email}",
                "#{list[" + index + "].name}"
            );
        }
        return sql.toString();
    }
}

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

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

写个测试看看具体效果

@SpringBootTest(classes = QuickStartApplication.class)
public class FluentMybatisApplicationTest {
    @Autowired
    private YourMapper yourMapper;
    
    void insertBatch(){
        List<YourEntity> entities = new ArrayList<>();
        entities.add(new YourEntity().setName("Fluent Mybatis").setEmail("darui.wu@163.com"));
        entities.add(new YourEntity().setName("Fluent Mybatis Demo").setEmail("darui.wu@163.com"));
        entities.add(new YourEntity().setName("Test4J").setEmail("darui.wu@163.com"));
        int count = yourMapper.insertBatch(entities);
        System.out.println("count:" + count);
        System.out.println("entity:" + entities);
    }
}

执行测试,查看控制台输出

DEBUG - ==>  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 - ==> Parameters: null, null, darui.wu@163.com(String), Fluent Mybatis(String), null, null, darui.wu@163.com(String), Fluent Mybatis Demo(String), null, null, darui.wu@163.com(String), Test4J(String) 
DEBUG - <==    Updates: 3 
count:3
entity:[YourEntity(id=null, gmtCreate=null, gmtModified=null, isDeleted=null, age=null, email=darui.wu@163.com, name=Fluent Mybatis), YourEntity(id=null, gmtCreate=null, gmtModified=null, isDeleted=null, age=null, email=darui.wu@163.com, name=Fluent Mybatis Demo), YourEntity(id=null, gmtCreate=null, gmtModified=null, isDeleted=null, age=null, email=darui.wu@163.com, name=Test4J)]
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值