Eloquent ORM for Java
- 注册配置 Configuration
- 数据映射 Mapping
- 数据模型 Model
- 查询结果集 Record
- 查询构造器 Query Builder
- 关联关系 Relationship
- 生成代码 Generate
- 单元测试 Test
- GraalVM
- 版本信息 Version
数据模型 Model是将数据库操作集中声明的对象, 理解为表
反向生成代码 Generate
重写getGaarasonDataSource
下面的例子使用spring注入后返回
GaarasonDataSource相关请看注册配置 Configuration
package temp.model.base;
import gaarason.database.connection.GaarasonDataSourceWrapper;
import gaarason.database.eloquent.Model;
import javax.annotation.Resource;
/**
* Model基类
* @param <T> 实体类
* @param <K> 实体类中的主键java类型, 不存在主键时, 可使用 Object
*/
abstract public class BaseModel<T, K> extends Model<MysqlBuilder<T, K>, T, K> {
@Resource
private GaarasonDataSource gaarasonDataSource;
@Override
public GaarasonDataSource getGaarasonDataSource() {
return gaarasonDataSource;
}
}子类只需要继承父类即可
package temp.model;
import temp.model.base.BaseModel;
import temp.pojo.Student;
import org.springframework.stereotype.Repository;
@Repository
public class StudentModel extends BaseModel<Student, Long> {
}Eloquent 模型,允许你在sql执行生命周期中的多个时间点调用如下这些方法:retrieving, retrieved, creating, created, updating, updated, saving, saved, deleting, deleted, forceDeleting, forceDeleted, restoring, restored。事件允许你在一个指定模型类每次保存或更新的时候执行代码。
- 其中以 eventRecord 为方法名前缀的事件, 一般 仅在使用 ORM 时, 触发
- 其中以 eventQuery 为方法名前缀的事件, ORM 以及 Query, 都会触发
- 原生语句 的查询方式, 不会触发任何事件
newQuery().get()/newQuery().first()等model.find()等
| 次序 | eventQuery | eventRecord |
|---|---|---|
| 1 | eventQueryRetrieving | |
| 2 | eventRecordRetrieved | |
| 3 | eventQueryRetrieved |
newQuery().insert()/newQuery().replace()/newQuery().upsert()等record.save()等
| 次序 | eventQuery | eventRecord |
|---|---|---|
| 1 | eventRecordSaving | |
| 2 | eventRecordCreating | |
| 3 | eventQueryCreating | |
| 4 | eventQueryCreated | |
| 5 | eventRecordCreated | |
| 6 | eventRecordSaved |
newQuery().update()等record.save()/record.saveByPrimaryKey()等
| 次序 | eventQuery | eventRecord |
|---|---|---|
| 1 | eventRecordSaving | |
| 2 | eventRecordUpdating | |
| 3 | eventQueryUpdating | |
| 4 | eventQueryUpdated | |
| 5 | eventRecordUpdated | |
| 6 | eventRecordSaved |
根据配置, 实际执行软删除或者硬删除
newQuery().delete()等record.delete()等
| 次序 | eventQuery | eventRecord |
|---|---|---|
| 1 | eventRecordDeleting | |
| 2 | eventQueryDeleting | |
| 3 | eventQueryUpdating | |
| 4 | eventQueryUpdated | |
| 5 | eventQueryDeleted | |
| 6 | eventRecordDeleted |
newQuery().delete()等record.delete()等
| 次序 | eventQuery | eventRecord |
|---|---|---|
| 1 | eventRecordDeleting | |
| 2 | eventQueryDeleting | |
| 3 | eventQueryForceDeleting | |
| 4 | eventQueryForceDeleted | |
| 5 | eventQueryDeleted | |
| 6 | eventRecordDeleted |
newQuery().restore()等record.restore()等
| 次序 | eventQuery | eventRecord |
|---|---|---|
| 1 | eventRecordRestoring | |
| 2 | eventQueryRestoring | |
| 3 | eventQueryUpdating | |
| 4 | eventQueryUpdated | |
| 5 | eventQueryRestored | |
| 6 | eventRecordRestored |
newQuery().forceDelete()等record.forceDelete()等
| 次序 | eventQuery | eventRecord |
|---|---|---|
| 1 | eventRecordForceDeleting | |
| 2 | eventQueryForceDeleting | |
| 3 | eventQueryForceDeleted | |
| 4 | eventRecordForceDeleted |
所有事件在ORM风格操作时时触发,ORM相关 事件可以继承自父类
则分别在删除以及恢复时触发。
ing结尾的事件, 均可以阻止事件的进行, 需要通过return false进行打断.
借用上面的model, 则一个事件的定义可以是以下形式
package temp.model;
import temp.model.base.BaseModel;
import temp.pojo.Student;
import org.springframework.stereotype.Repository;
@Repository
public class StudentModel extends BaseModel<Student, Long> {
@Override
public void eventRecordRetrieved(Record<Student, Long> entityRecord){
System.out.println("已经从数据库中查询到数据");
}
@Override
public boolean eventRecordUpdating(Record<Student, Long> record){
if(record.getEntity().getId() == 9){
System.out.println("正要修改id为9的数据, 但是拒绝");
return false;
}
return true;
}
}所有事件在Query风格操作时时触发,Query相关 事件可以继承自父类
ing结尾的事件, 均可以阻止查询的进行, 需要通过异常进行打断.
借用上面的model, 则一个事件的定义可以是以下形式
package temp.model;
import temp.model.base.BaseModel;
import temp.pojo.Student;
import org.springframework.stereotype.Repository;
@Repository
public class StudentModel extends BaseModel<Student, Long> {
@Override
public void eventQueryRetrieved(Record<Student, Long> entityRecord){
System.out.println("已经从数据库中查询到数据");
}
@Override
public void eventQueryUpdating(Builder<Student, Integer> builder){
// 通过事件, 增加自定义的条件
builder.where("xxx", "x");
}
}需要注意的是, eventQueryCreated方法包含3个不同的方法重载, 分别对应不同的响应类型.
- 通过在模型上, 定义注解
@ObservedBy(), 可以将事件逻辑从模型上分离出去 @ObservedBy()可以同时声明多个事件处理器, 他们将依次按序执行事件处理器需要实现Event接口@ObservedBy()可以被继承, 在父model上声明, 可以被子类锁触发
// model 定义
@ObservedBy(StudentEvent.class)
public class StudentEventV2Model extends SingleModel<StudentEventV2Model.Entity, Integer> {
}// 事件处理程序定义
import gaarason.database.contract.model.Event;
public static class StudentEvent implements Event<MySqlBuilderV2<StudentEventV2Model.Entity, Integer>, StudentEventV2Model.Entity, Integer>{
@Override
public boolean eventRecordCreating(Record<Entity, Integer> record) {
Entity entity = record.getEntity();
// 不让 age 66 更新成功
return entity.age != 66;
}
}- 为了避免
事务回滚导致的虚假事件, 我们会希望, 数据库事务提交成功后, 再执行其事件处理程序 - 通过实现
ShouldHandleEventsAfterCommit接口来实现这一点 - 如果没有正在进行的数据库事务,事件处理程序将和之前一样, 立即执行
- 值的注意的是, 此功能仅会影响
ed类型的事件 - 事务成功提交后的事件, 将会使用
快照参数进行回调 - 多个事务嵌套时, 会在最外层事务成功提交后再触发
- 此外, 即使没有使用
@ObservedBy()声明专用的事件处理器, 也可以在model上实现ShouldHandleEventsAfterCommit达到一样的效果
import gaarason.database.contract.model.Event;
import gaarason.database.contract.support.ShouldHandleEventsAfterCommit;
public static class StudentEvent implements Event<MySqlBuilderV2<StudentEventV2Model.Entity, Integer>, StudentEventV2Model.Entity, Integer>,
ShouldHandleEventsAfterCommit {
@Override
public void eventRecordUpdated(Record<Entity, Integer> record) {
Entity entity = record.getEntity();
// .....
}
}- 在
查询构造器中, 通过quiet()包装的逻辑, 将不会触发任何事件 - 不支持在此中进行线程切换
newQuery().quiet(() -> {
// .... 不会触发事件
newQuery().get();
});- 在
Record中同样提供了更加便捷的静默方法
record.saveQuietly();
record.saveByPrimaryKeyQuietly();
record.deleteQuietly();
record.forceDeleteQuietly();
record.restoreQuietly();
record.restoreQuietly(boolean);在父类或者底层限制数据查询的有效范围
package temp.model;
import temp.model.base.BaseModel;
import temp.pojo.Student;
import org.springframework.stereotype.Repository;
@Repository
public class StudentModel extends BaseModel<Student, Long> {
/**
* 全局查询作用域
* @param builder 查询构造器
* @return 查询构造器
*/
protected Builder<Student, Long> apply(Builder<Student, Long> builder) {
// return builder->where("type", "2");
return builder;
}
}- 软删除相关实现, 重写
gaarason.database.eloquent.query.BaseSoftDeleting的相关方法 - 开启软删除, 重写
softDeleting方法结果为true
package temp.model;
import temp.model.base.BaseModel;
import temp.pojo.Student;
import org.springframework.stereotype.Repository;
@Repository
public class StudentModel extends BaseModel<Student, Long> {
/**
* 是否启用软删除
*/
protected boolean softDeleting() {
return false;
}
/**
* 删除(软/硬删除)
* @param builder 查询构造器
* @return 删除的行数
*/
public int delete(Builder<Student, Long> builder) {
return softDeleting() ? softDelete(builder) : builder.forceDelete();
}
/**
* 恢复软删除
* @param builder 查询构造器
* @return 删除的行数
*/
public int restore(Builder<Student, Long> builder) {
return softDeleteRestore(builder);
}
/**
* 软删除查询作用域(反)
* @param builder 查询构造器
*/
protected void scopeSoftDeleteOnlyTrashed(Builder<Student, Long> builder) {
builder.where("is_deleted", "1");
}
/**
* 软删除查询作用域(反)
* @param builder 查询构造器
*/
protected void scopeSoftDeleteWithTrashed(Builder<Student, Long> builder) {
}
/**
* 软删除查询作用域
* @param builder 查询构造器
*/
protected void scopeSoftDelete(Builder<Student, Long> builder) {
builder.where("is_deleted", "0");
}
/**
* 软删除实现
* @param builder 查询构造器
* @return 删除的行数
*/
protected int softDelete(Builder<Student, Long> builder) {
return builder.data("is_deleted", "1").update();
}
/**
* 恢复软删除实现
* @param builder 查询构造器
* @return 恢复的行数
*/
protected int softDeleteRestore(Builder<Student, Long> builder) {
return builder.data("is_deleted", "0").update();
}
}