Tigon MyBatis

为 Mapper 提供增强
授权协议 BSD-2-Clause
开发语言 Java
所属分类 程序开发、 ORM/持久层框架
软件类型 开源软件
地区 国产
投 递 者 范豪
操作系统 跨平台
开源组织
适用人群 未知
 软件概览

Tigon MyBatis为Spring工程中MyBatis的Mapper提供增强,主要有以下特点:

  • 代码又少又壮,绝不做多余的事情
  • 仅需Mapper继承接口,实现   ,无额外配置,爽到没女朋友
  • 用完即走,毫不留恋

开始使用

  • 引入Maven依赖
<dependency>
  <groupId>me.chyxion.tigon</groupId>
  <artifactId>tigon-mybatis</artifactId>
  <version>0.0.4</version>
</dependency>

使用示例

下面是使用示例,可以在源代码中找到更详细的单元测试。Talk is cheep,read the fine source code.

定义Entity

package me.chyxion.tigon.mybatis.entity;

import lombok.Getter;
import lombok.Setter;
import java.util.Date;
import lombok.ToString;
import java.io.Serializable;
import me.chyxion.tigon.mybatis.Table;
import me.chyxion.tigon.mybatis.NotUpdate;

@Getter
@Setter
@ToString
@Table("tb_user")
public class User implements Serializable {
    private static final long serialVersionUID = 1L;

    private Integer id;
    @NotUpdate
    private String account;
    private String mobile;
    private String name;
    private Gender gender;
    private String password;
    private Date birthDate;
    private String city;
    private String avatar;

    private Boolean active;
    private String remark;
    private String createdBy;
    private Date createdAt;
    private String updatedBy;
    private Date updatedAt;

    public enum Gender {
        MALE,
        FEMALE
    }
}

定义Mapper

package me.chyxion.tigon.mybatis.mapper;

import java.util.List;
import me.chyxion.tigon.mybatis.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import me.chyxion.tigon.mybatis.entity.User;

@Mapper
public interface UserMapper extends BaseMapper<Integer, User> {
}

注入Mapper对象

@Autowired
private UserMapper mapper;

I. 插入

final User user = new User();
user.setName("Donghuang");
user.setAccount("donghuang");
user.setMobile("137647788xx");
user.setPassword(RandomStringUtils.randomAlphanumeric(16));
user.setGender(User.Gender.MALE);
user.setBirthDate(DateUtils.parseDate("1994-04-04"));
user.setCity("Shanghai");
user.setActive(true);
user.setRemark("Uncle Donghuang");
user.setCreatedBy("donghuang");
user.setCreatedAt(new Date());

// single insert
mapper.insert(user);

final User user1 = new User();
user1.setName("Gemily");
user1.setAccount("gemily");
user1.setMobile("15770780xxx");
user1.setPassword(RandomStringUtils.randomAlphanumeric(16));
user1.setGender(User.Gender.FEMALE);
user1.setBirthDate(DateUtils.parseDate("1990-06-06"));
user1.setCity("Hangzhou");
user1.setActive(true);
user1.setCreatedBy("donghuang");
user1.setCreatedAt(new Date());

final User user2 = new User();
user2.setName("Luffy");
user2.setAccount("luffy");
user2.setMobile("137647799xx");
user2.setPassword(RandomStringUtils.randomAlphanumeric(16));
user2.setGender(User.Gender.MALE);
user2.setBirthDate(DateUtils.parseDate("1997-07-07"));
user2.setCity("East sea");
user2.setActive(true);
user2.setRemark("Luffy");
user2.setCreatedBy("donghuang");
user2.setCreatedAt(new Date());

// batch insert
mapper.insert(Arrays.asList(user1, user2));

II. 查询

根据ID查询单个对象

final Integer id = 1154;
final User user = mapper.find(id);

根据属性查询单个对象

final User user = mapper.find(
    new Search("account", "donghuang")
        .eq("mobile", "137647788xx"));

根据属性查询列表

final List<User> users = mapper.list(new Search()
    .between("birth_date",
        DateUtils.parseDate("1982-04-04"),
        DateUtils.parseDate("1994-04-04")
    )
    .eq("gender", User.Gender.MALE)
    .asc("birth_date")
    .limit(42));

Search对象支持的API

  • and And another Search
  • asc Order ASC
  • between Between two values
  • build Build query criterion
  • contains Value contains string
  • desc Order DSC
  • endsWith Value ends with string
  • eq Eqauls
  • gt Greater than
  • gte Eqauls or greater than
  • in In values
  • isNull Value is null
  • like Value like
  • limit Return rows limit
  • lt Less than
  • lte Eqauls or less than
  • ne Not equals
  • notIn Not in values
  • notNull Value is not null
  • offset Return rows offset
  • or Or another Search
  • orderBy Order by
  • startsWith Value starts with string

III. 更新

通过Entity根据ID更新

final User user = mapper.find(1);

user.setName("东皇大叔");
user.setUpdatedBy("SYS");
user.setUpdatedAt(new Date());

mapper.update(user);

通过Map<String, Object>更新

final Map<String, Object> update = new HashMap<>(6);
update.put("name", "东皇大叔");
update.put("updatedBy", "SYS");
update.put("updatedAt", new Date());

mapper.update(update, 1);
// OR
// mapper.update(update, new Search("id", 1));
// mapper.update(update, new Search(1));

更新列为NULL

// Update remark to NULL of id 274229
mapper.setNull("remark", 274229);
// Update remark to NULL of id 1154L
mapper.setNull("remark", new Search("id", 1154));
// Update all remarks to NULL. BE CAREFUL!!!
mapper.setNull("remark", new Search());

IV. 删除

通过ID删除数据

mapper.delete(1);

通过Search对象删除数据

mapper.delete(new Search("id", 1));

V. 杂项

除了上面说到的一些基础增删改查操作,还有一些实用功能,如@Transient @UseGeneratedKeys @NoPrimaryKey @NotUpdateWhenNull @RawValue等注解,插入、更新前回调,以及支持扩展自定义的方法等。

配置说明

  • SpringBoot项目,无需其他操作,引入依赖即可
  • Spring项目,注册Bean me.chyxion.tigon.mybatis.TigonMyBatisConfiguration
  • 业务Mapper继承me.chyxion.tigon.mybatis.BaseMapper或相关衍生Mapper,Base(Query, Insert, Update, Delete)Mapper

原理

Tigon MyBatis并不改变MyBatis相关功能,所做的只是在程序启动期间检测业务Mapper接口,如果继承了相关BaseMapper.java,则注入相关方法MappedStatement,具体逻辑参见源码,超简单,超幼稚。

其他

在前面使用Search的例子中,我们需要一些User的属性常量字符串,比如

final User user = mapper.find(new Search("account", "donghuang"));

可以将这些常量定义在User类中,如

public static final String ACCOUNT = "account";

使用过程中可以使用属性常量,如

final User user = mapper.find(new Search(User.ACCOUNT, "donghuang"));

也可以使用Lombok@FieldNameConstants注解生成,只是这个注解还处于试验阶段,有一定不稳定风险。

最后

为什么要有这个项目,其实这些代码本人从2014年就陆续在写在用,在自己参与的一些项目里默默奉献。

有想过开源,奈何一直忙着修福报,此外很重要的一点是,觉得方案并不完善,还是比较长比较臭。

开源界已经有很多MyBatis相关的项目了,包括官方出品的mybatis-dynamic-sql,这玩意把我可恶心坏了。最近接触的项目里有在用,看着那一坨一坨的完全没动力碰的垃圾代码,全世界都在看我们的笑话,Java什么时候变成这样了,让玩PHP,玩C#,玩GO,玩Ruby的同学怎么看待我们,哎卧槽。

魔幻2020年就快结束了,熬夜把拖延了好几年的待办事项做个了结,后续如果还有精力,我会考虑把生成代码的逻辑一并释放出来。

 相关资料
  • 我正在尝试反序列化两种类型的json: 和 进入这些对象: 第一种方法创建两个新对象,第二种方法基于字符串的内容从数据库请求对象。 有点像杰克逊映射器如何将任意字符串反序列化为对象,对于这样的对象: 问题是我两者都需要。我需要它来处理对象和字符串。两者都可以从同一个输入到达。 我尝试的第一个想法是制造一个转换器 它说这些创建一个委托类型来传递给反序列化器,但是即使数据类型不是字符串,转换器也总是被

  • Microsoft Office Visual Basic 对象模型进行了广泛改进,以支持共享组件中的新增和改进功能,添加了很多对象、属性、方法和事件。 请访问 MSDN Online 上的 Office 开发人员中心获取最新的 Microsoft Office 开发信息,包括新技术文章、下载、范例、产品新闻等更多内容。 新增语言元素 下列主题提供了 Office 中新增语言元素的列表: 新增对象

  • 我正在我的服务中添加SSO功能,以允许客户使用他们的广告帐户登录。为此,我使用componentpro中的SAML组件。com执行安全交互的正确方法是什么: < li >从IdP方面:除了IdP url,客户还应该向我的服务提供什么?任何只包含公钥的证书? < li >从服务提供商的角度:我应该向客户提供什么? < li >选择的SAML工具使用证书对发送给IdP的SAML请求进行签名,并对来自I

  • 通用 Mapper4 是一个可以实现任意 MyBatis 通用方法的框架,项目提供了常规的增删改查操作以及Example 相关的单表操作。通用 Mapper 是为了解决 MyBatis 使用中 90% 的基本操作,使用它可以很方便的进行开发,可以节省开发人员大量的时间。 通用Mapper都可以极大的方便开发人员。可以随意的按照自己的需要选择通用方法,还可以很方便的开发自己的通用方法。 极其方便的使

  • Mapper 是一个简单的 Swift 库,用于转换 JSON 为强类型对象。和其它库相比,Mapper 的一个优点是你可以有不可改变的特性。 代码: import Mapper// Conform to the Mappable protocolstruct User: Mappable {  let id: String  let photoURL: NSURL?  // Implement 

  • 问题内容: 我正在使用: Python 3.4.2 PyMongo 3.0.2 mongolab运行mongod 2.6.9 uWSGI 2.0.10 CherryPy 3.7.0 nginx 1.6.2 uWSGI启动参数: 我一次设置了MongoClient: 我尝试将JSON字典保存到MongoDB: 它通过执行与mongodb相同的代码路径的单元测试来工作。但是,当我使用HTTP POST

  • 我有一个在 jasper 工作室设计的 jrxml 报告文件: 我点击了此处的链接将其与冲刺启动应用程序集成 spring框架和spring JPA中的Jasper report 运行应用程序时出现以下错误,并显示一个空白报告。 Pleassssssse 帮助我将从工作室生成的报告集成到Spring启动。 (我是java新手) 这里是我的报表控制器方法 我正在传递 json 数据作为数据源