# mybatis-milu
**Repository Path**: trf/mybatis-milu
## Basic Information
- **Project Name**: mybatis-milu
- **Description**: mybatis增强框架
- **Primary Language**: Java
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 8
- **Created**: 2024-12-12
- **Last Updated**: 2024-12-12
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# mybatis-milu
[详细文档](http://mybatis-milu.yuehuanghun.com/)
[示范项目yadmin](https://gitee.com/yuehh/yadmin4j)
### 介绍
mybatis-milu是基于mybatis的功能增强框架,遵循JPA规范的超轻量ORM拓展,提供通用Mapper接口,提供类似Spring Data JPA的查询创建器,通过方法名解析查询语句,极大提高开发效率。
本框架仅做功能增强,拓展statement的创建方式,不覆盖mybatis中的任何实现。
支持JPA的注解规范,但没有根据实体类注解声明生成表、索引等的功能,所以部分注解或注解属性用来生成表及索引的,使用后并无效果。
功能视图:
#### 目标
1. 通过ORM使9成以上查询不需要写SQL就能完成,减少SQL测试调试时间。
2. 通过ORM解决多表关联查询问题,避免一涉及多表查询就要写SQL的问题。
3. 通过命名查询创建器更方便创建一对一的专用查询接口,更容易审计。
### 软件架构
依赖
mybatis >= 3.5.0
pagehelper >=5.1.0
jdk >= 1.8
### 安装教程
```
com.yuehuanghun
mybatismilu-spring-boot-starter
1.18.0
com.yuehuanghun
mybatismilu-spring-boot3-starter
1.18.0
```
### 核心功能

### 示范项目
基于知名的开源项目“若依管理系统”改版的项目:[yadmin](https://gitee.com/yuehh/yadmin4j)
#### 一、实体类声明
如果你熟悉使用Hibernate等JPA框架,以下内容你会比较容易理解。
使用javax.persistence.Entity注解一个类为实体类。
可以使用javax.persistence.Table注解声明覆盖实体类的默认值。
可以使用javax.persistence.Column注解声明覆盖字段的默认值。
使用javax.persistence.Id注解声明这个属性为表的主键。
使用javax.persistence.Transient注解声明属性为非表字段或关联。
使用javax.persistence.OneToOne声明一对一的关系。
使用javax.persistence.ManyToOne声明多对一的关系。
使用javax.persistence.OneToMany声明一对多的关系
使用javax.persistence.ManyToMany声明多对多的关系
使用javax.persistence.JoinColumn声明实体(表)关联的信息
使用javax.persistence.JoinTable声明实体(表)关联的信息
```
@Data
@Entity
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.TABLE, generator = "tableSequence")
@TableGenerator(name = "tableSequence", table = "sequence", valueColumnName = "current_seq", pkColumnName = "id", pkColumnValue = "1")
private Long id; //使用数据表模拟数字序列
@AttributeOptions(filler = @Filler(fillOnInsert = true)) //当在插入数据时,如果该属性为null则自动填充值
private Date addTime;
@AttributeOptions(filler = @Filler(fillOnInsert = true, fillOnUpdate = true)) //当在插入或更新数据时,如果该属性为null则自动填充值
private Date updateTime;
@AttributeOptions(exampleQuery = @ExampleQuery(matchType = MatchType.CONTAIN)) //使用findByExample方法时name不为空时,即执行name LIKE %nameValue%
private String name;
private Integer age;
private Long classId;
@ManyToOne
@JoinColumn(name = "class_id", referencedColumnName = "id")
private Classs classs; //对多一引用
@OneToOne(mappedBy = "student")
private StudentProfile studentProfile; //一对一引用
}
```
```
@Entity
@Table(name = "class")
// @Table(name = "class", schema="指定schema") //指定schema可以访问非当前数据源默认库
@Data
public class Classs {
@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = Constants.ID_GENERATOR_SNOWFLAKE)
private Long id; //使用分布式ID,内置的snowflakeId
private Date addTime;
private String name;
@ManyToMany(mappedBy = "classList")
private List teacherList; //多对多关系演示,双向引用
@OneToMany(mappedBy = "classs")
private List studentList; //一对多关系演示,双向引用
}
```
##### 注解别名
一些注解声明可配置项比较多并复杂,会比较美感度。
从1.2.0版本开始,在用注解声明实体信息时,可以对@Id、@AttributeOptions自定义一个配置的别名注解,降低配置声明的繁杂度
内置对ID字段的注解别名:@SnowflakeId、@UUID
```
@Retention(RUNTIME)
@Target(FIELD)
public @interface SnowflakeId {
@Id
@GeneratedValue(generator = Constants.ID_GENERATOR_SNOWFLAKE)
String value() default StringUtils.EMPTY;
}
@Retention(RUNTIME)
@Target(FIELD)
public @interface UUID {
@Id
@GeneratedValue(generator = Constants.ID_GENERATOR_UUID)
String value() default StringUtils.EMPTY;
}
```
使得
```
public class SomeEntity {
@SnowflakeId
private Long id;
}
//等同于
public class SomeEntity {
@Id
@GeneratedValue(generator = Constants.ID_GENERATOR_SNOWFLAKE)
private Long id;
}
```
这样既简便又明了。
内置对通用字段的@AttributeOptions配置声明别名注解:@CrateTime、@UpdateTime
```
@Retention(RUNTIME)
@Target(FIELD)
public @interface CreateTime {
@AttributeOptions(filler = @Filler(fillOnInsert = true))
@Column(updatable = false)
String value() default StringUtils.EMPTY;
}
@Retention(RUNTIME)
@Target(FIELD)
@AttributeOptions(filler = @Filler(fillOnInsert = true, fillOnUpdate = true))
public @interface UpdateTime {
}
```
```
public class SomeEntity {
@CreateTime
private LocalDateTime CreateTime;
}
//等同于
public class SomeEntity {
@AttributeOptions(filler = @Filler(fillOnInsert = true)) //插入数据时自动添加当前日期,无需手动设值
@Column(updatable = false) //不可更新
private LocalDateTime CreateTime;
}
```
别名注解可以自定义,目前可以被配置的有@Id、@GeneratedValue、@AttributeOptions、@Column
自定义可以参考示范项目
##### MyBatis-Milu中的自定义注解
JPA提供注解未能完全满足需要,因此也有一些此框架中自定义的注解
为了方便记忆,大部分拓展配置都可以通过以下三个注解进行声明,可以通过类的注释内容了解它们的功能
1. EnityOptions
实体选项
2. AttributeOptions
实体属性的选项
3. StatementOptions
Mapper查询方法的选项
#### 二、通用Mapper
Mapper接口通过继承BaseMapper接口类,获得通用的数据访问能力。
以下对一些特别的接口进行说明,简单的接口不再说明:
##### 1、example查询,使用entity对象作为查询条件。findByExample、findUniqueByExample、countByExample
使用实体类对象作为查询条件。
默认情况下entity的属性值不为空时(not empty模式),将被作为查询条件,可以使用@AttributeOptions(conditionMode=Mode.xxx)更改条件的生效模式。
默认情况下属性作为查询条件时,使用值=匹配,可以@AttributeOptions(exampleQuery=@ExampleQuery(matchType=MatchType.xxx))更改查询匹配方式
同样适用
默认只查询主体的字段,如果你希望返回引用属性(关联表)的数据,可以在实体类上使用@FetchRef或@EntityOptions(fetchRefs={@FetchRef})进行声明
从1.12.0版本开始,example查询默认自动查询未删除数据的条件,并联表同理,如需关闭,需在实体类上添加@EntityOptions(filterLogicDeletedData = false)
###### example中的范围查询
通过@AttributeOptions(exampleQuery=@ExampleQuery(startKeyName="", endKeyName=""))指定传值的参数名
@AttributeOptions(exampleQuery=@ExampleQuery(startValueContain=true, endValueContain=true)) 可指定范围是开区间还是闭区间
```java
@AttributeOptions(exampleQuery=@ExampleQuery(startKeyName="params.createTimeBegin", endKeyName="params.createTimeEnd"))
LocalDateTime createTime();
// SomeEntity example = new SomeEntity();
// example.getParams.put("createTimeBegin", LocalDateTime.now());
```
当范围是集合时,可使用@AttributeOptions(exampleQuery=@ExampleQuery(inKeyName=""))指定传值的参数名
值可为集合、数组或以半角逗号隔开多值的字符串。
```java
@AttributeOptions(exampleQuery=@ExampleQuery(startKeyName="inKeyName="params.statusList"))
String status();
// SomeEntity example = new SomeEntity();
// example.getParams.put("statusList", "1,2,3");
// 或
// example.getParams.put("statusList", new String[]{"1","2","3"});
```
##### 2、criteria查询。findByCriteria、updateByCriteria、deleteByCriteria、countByCriteria
自定义条件查询,通过实体属性设置查询条件
```java
//方式一
List list = classMapper.findByCriteria(new QueryPredicateImpl().eq("name", "一年级").order(Direction.DESC,"id").order("studentListAddTime"));
//方式二
List list = classMapper.findByCriteria(p -> p.eq("name", "一年级").order(Direction.DESC,"id").order("studentListAddTime"));
//查询多表
List list = classMapper.findByCriteria(p -> p.select("*","studentList*").eq("id", 1L));
```
##### 3、lambdaCriteria查询。findByLambdaCriteria、updateByLambdaCriteria、deleteByLambdaCriteria、countByLambdaCriteria
自定义条件查询,通过实体属性的lambda函数式设置查询条件
```java
Classs params = new Classs();
params.setName("一年级");
//方式一
List list = classMapper.findByLambdaCriteria(predicate -> predicate.apply(params).select(Classs::getName, Classs::getAddTime).eq(Classs::getName).limit(10, false));
//方式二
List list = classMapper.findByLambdaCriteria(predicate -> predicate.select(Classs::getName, Classs::getAddTime).eq(Classs::getName, params.getName()).limit(10, false));
//查询多表
List list = classMapper.findByLambdaCriteria(p -> p.select("*","studentList*").eq(Classs::getId, 1L));
```
##### 4、criteria、lambdaCriteria统计
目前支持5个统计关键字:sum/count/min/max/avg
```
List