Tigon MyBatis為 Mapper 提供增強(qiáng)
Tigon MyBatis為Spring工程中MyBatis的Mapper提供增強(qiáng),主要有以下特點(diǎn):
- 代碼又少又壯,絕不做多余的事情
- 僅需Mapper繼承接口,實(shí)現(xiàn)
增刪改查,無額外配置,爽到?jīng)]女朋友 - 用完即走,毫不留戀
開始使用
- 引入Maven依賴
<dependency> <groupId>me.chyxion.tigon</groupId> <artifactId>tigon-mybatis</artifactId> <version>0.0.4</version> </dependency>
使用示例
下面是使用示例,可以在源代碼中找到更詳細(xì)的單元測(cè)試。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對(duì)象
@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. 查詢
根據(jù)ID查詢單個(gè)對(duì)象
final Integer id = 1154; final User user = mapper.find(id);
根據(jù)屬性查詢單個(gè)對(duì)象
final User user = mapper.find( new Search("account", "donghuang") .eq("mobile", "137647788xx"));
根據(jù)屬性查詢列表
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對(duì)象支持的API
-
andAnd anotherSearch -
ascOrder ASC -
betweenBetween two values -
buildBuild query criterion -
containsValue contains string -
descOrder DSC -
endsWithValue ends with string -
eqEqauls -
gtGreater than -
gteEqauls or greater than -
inIn values -
isNullValue is null -
likeValue like -
limitReturn rows limit -
ltLess than -
lteEqauls or less than -
neNot equals -
notInNot in values -
notNullValue is not null -
offsetReturn rows offset -
orOr anotherSearch -
orderByOrder by -
startsWithValue starts with string
III. 更新
通過Entity根據(jù)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刪除數(shù)據(jù)
mapper.delete(1);
通過Search對(duì)象刪除數(shù)據(jù)
mapper.delete(new Search("id", 1));
V. 雜項(xiàng)
除了上面說到的一些基礎(chǔ)增刪改查操作,還有一些實(shí)用功能,如@Transient @UseGeneratedKeys @NoPrimaryKey @NotUpdateWhenNull @RawValue等注解,插入、更新前回調(diào),以及支持?jǐn)U展自定義的方法等。
配置說明
- SpringBoot項(xiàng)目,無需其他操作,引入依賴即可
- Spring項(xiàng)目,注冊(cè)Bean me.chyxion.tigon.mybatis.TigonMyBatisConfiguration
- 業(yè)務(wù)Mapper繼承me.chyxion.tigon.mybatis.BaseMapper或相關(guān)衍生Mapper,Base(Query, Insert, Update, Delete)Mapper
原理
Tigon MyBatis并不改變MyBatis相關(guān)功能,所做的只是在程序啟動(dòng)期間檢測(cè)業(yè)務(wù)Mapper接口,如果繼承了相關(guān)BaseMapper.java,則注入相關(guān)方法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注解生成,只是這個(gè)注解還處于試驗(yàn)階段,有一定不穩(wěn)定風(fēng)險(xiǎn)。
最后
為什么要有這個(gè)項(xiàng)目,其實(shí)這些代碼本人從2014年就陸續(xù)在寫在用,在自己參與的一些項(xiàng)目里默默奉獻(xiàn)。
有想過開源,奈何一直忙著修福報(bào),此外很重要的一點(diǎn)是,覺得方案并不完善,還是比較長比較臭。
開源界已經(jīng)有很多MyBatis相關(guān)的項(xiàng)目了,包括官方出品的mybatis-dynamic-sql,這玩意把我可惡心壞了。最近接觸的項(xiàng)目里有在用,看著那一坨一坨的完全沒動(dòng)力碰的垃圾代碼,全世界都在看我們的笑話,Java什么時(shí)候變成這樣了,讓玩PHP,玩C#,玩GO,玩Ruby的同學(xué)怎么看待我們,哎臥槽。
魔幻2020年就快結(jié)束了,熬夜把拖延了好幾年的待辦事項(xiàng)做個(gè)了結(jié),后續(xù)如果還有精力,我會(huì)考慮把生成代碼的邏輯一并釋放出來。
