This commit is contained in:
开源海哥 2023-04-28 19:59:40 +08:00
commit 5d7da4a2bb
16 changed files with 323 additions and 71 deletions

View File

@ -0,0 +1,29 @@
package com.mybatisflex.annotation;
/**
* 类型支持 insert 监听器
*
* @author snow
* @since 2023/4/28
*/
public abstract class AbstractInsertListener<T> implements InsertListener {
/**
* 该监听器支持的entity类型
*
* @return type
*/
public abstract Class<T> supportType();
public abstract void doInsert(T entity);
@Override
@SuppressWarnings("unchecked")
public void onInsert(Object entity) {
Class<T> supportType = supportType();
if (supportType.isInstance(entity)) {
T object = (T) entity;
doInsert(object);
}
}
}

View File

@ -0,0 +1,28 @@
package com.mybatisflex.annotation;
/**
* 类型支持 update 监听器
*
* @author snow
* @since 2023/4/28
*/
public abstract class AbstractUpdateListener<T> implements UpdateListener {
/**
* 该监听器支持的entity类型
*
* @return type
*/
public abstract Class<T> supportType();
public abstract void doUpdate(T entity);
@Override
@SuppressWarnings("unchecked")
public void onUpdate(Object entity) {
Class<T> supportType = supportType();
if (supportType.isInstance(entity)) {
T object = (T) entity;
doUpdate(object);
}
}
}

View File

@ -15,6 +15,6 @@
*/ */
package com.mybatisflex.annotation; package com.mybatisflex.annotation;
public interface InsertListener { public interface InsertListener extends Listener{
void onInsert(Object entity); void onInsert(Object entity);
} }

View File

@ -0,0 +1,25 @@
package com.mybatisflex.annotation;
/**
* 监听器
*
* @author snow
* @since 2023/4/28
*/
public interface Listener extends Comparable<Listener> {
/**
* 多个监听器时的执行顺序
* <p>值越小越早触发执行</p>
*
* @return order
*/
default int order() {
return Integer.MAX_VALUE;
}
@Override
default int compareTo(Listener other) {
return order() - other.order();
}
}

View File

@ -15,7 +15,7 @@
*/ */
package com.mybatisflex.annotation; package com.mybatisflex.annotation;
public class NoneListener implements InsertListener, UpdateListener, SetListener { public final class NoneListener implements InsertListener, UpdateListener, SetListener {
@Override @Override
public void onInsert(Object entity) { public void onInsert(Object entity) {

View File

@ -15,7 +15,7 @@
*/ */
package com.mybatisflex.annotation; package com.mybatisflex.annotation;
public interface SetListener { public interface SetListener extends Listener {
Object onSet(Object entity, String property, Object value); Object onSet(Object entity, String property, Object value);
} }

View File

@ -15,7 +15,10 @@
*/ */
package com.mybatisflex.annotation; package com.mybatisflex.annotation;
import java.lang.annotation.*; import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE}) @Target({ElementType.TYPE})
@ -44,17 +47,17 @@ public @interface Table {
/** /**
* 监听 entity insert 行为 * 监听 entity insert 行为
*/ */
Class<? extends InsertListener> onInsert() default NoneListener.class; Class<? extends InsertListener>[] onInsert() default {};
/** /**
* 监听 entity update 行为 * 监听 entity update 行为
*/ */
Class<? extends UpdateListener> onUpdate() default NoneListener.class; Class<? extends UpdateListener>[] onUpdate() default {};
/** /**
* 监听 entity 的查询数据的 set 行为用户主动 set 不会触发 * 监听 entity 的查询数据的 set 行为用户主动 set 不会触发
*/ */
Class<? extends SetListener> onSet() default NoneListener.class; Class<? extends SetListener>[] onSet() default {};
/** /**
* 在某些场景下我们需要手动编写 Mapper可以通过这个注解来关闭 APT Mapper 生成 * 在某些场景下我们需要手动编写 Mapper可以通过这个注解来关闭 APT Mapper 生成

View File

@ -15,7 +15,7 @@
*/ */
package com.mybatisflex.annotation; package com.mybatisflex.annotation;
public interface UpdateListener { public interface UpdateListener extends Listener {
void onUpdate(Object entity); void onUpdate(Object entity);

View File

@ -16,13 +16,15 @@
package com.mybatisflex.core; package com.mybatisflex.core;
import com.mybatisflex.annotation.InsertListener; import com.mybatisflex.annotation.InsertListener;
import com.mybatisflex.annotation.KeyType;
import com.mybatisflex.annotation.SetListener; import com.mybatisflex.annotation.SetListener;
import com.mybatisflex.annotation.UpdateListener; import com.mybatisflex.annotation.UpdateListener;
import com.mybatisflex.core.dialect.DbType; import com.mybatisflex.core.dialect.DbType;
import com.mybatisflex.annotation.KeyType;
import org.apache.ibatis.session.Configuration; import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -157,16 +159,66 @@ public class FlexGlobalConfig {
return entitySetListeners.get(entityClass); return entitySetListeners.get(entityClass);
} }
/**
* 获取支持该 {@code entityClass} 的set监听器
* <p>当registerClass是entityClass的本身或其超类时则视为支持</p>
*
* @param entityClass 实体class
* @return UpdateListener
*/
public List<SetListener> getSupportedSetListener(Class<?> entityClass) {
List<SetListener> list = new ArrayList<>();
for (Class<?> registerClass : entitySetListeners.keySet()) {
if (registerClass.isAssignableFrom(entityClass)) {
list.add(entitySetListeners.get(registerClass));
}
}
return list;
}
public UpdateListener getUpdateListener(Class<?> entityClass) { public UpdateListener getUpdateListener(Class<?> entityClass) {
return entityUpdateListeners.get(entityClass); return entityUpdateListeners.get(entityClass);
} }
/**
* 获取支持该 {@code entityClass} 的update监听器
* <p>当registerClass是entityClass的本身或其超类时则视为支持</p>
*
* @param entityClass 实体class
* @return UpdateListener
*/
public List<UpdateListener> getSupportedUpdateListener(Class<?> entityClass) {
List<UpdateListener> list = new ArrayList<>();
for (Class<?> registerClass : entityUpdateListeners.keySet()) {
if (registerClass.isAssignableFrom(entityClass)) {
list.add(entityUpdateListeners.get(registerClass));
}
}
return list;
}
public InsertListener getInsertListener(Class<?> entityClass) { public InsertListener getInsertListener(Class<?> entityClass) {
return entityInsertListeners.get(entityClass); return entityInsertListeners.get(entityClass);
} }
/**
* 获取支持该 {@code entityClass} 的insert监听器
* <p>当registerClass是entityClass的本身或其超类时则视为支持</p>
*
* @param entityClass 实体class
* @return InsertListener
*/
public List<InsertListener> getSupportedInsertListener(Class<?> entityClass) {
List<InsertListener> list = new ArrayList<>();
for (Class<?> registerClass : entityInsertListeners.keySet()) {
if (registerClass.isAssignableFrom(entityClass)) {
list.add(entityInsertListeners.get(registerClass));
}
}
return list;
}
public Object getNormalValueOfLogicDelete() { public Object getNormalValueOfLogicDelete() {
return normalValueOfLogicDelete; return normalValueOfLogicDelete;

View File

@ -86,9 +86,9 @@ public class TableInfo {
private Map<String, ColumnInfo> columnInfoMapping = new HashMap<>(); private Map<String, ColumnInfo> columnInfoMapping = new HashMap<>();
private Map<String, String> propertyColumnMapping = new HashMap<>(); private Map<String, String> propertyColumnMapping = new HashMap<>();
private InsertListener onInsertListener; private List<InsertListener> onInsertListener;
private UpdateListener onUpdateListener; private List<UpdateListener> onUpdateListener;
private SetListener onSetListener; private List<SetListener> onSetListener;
private final ReflectorFactory reflectorFactory = new BaseReflectorFactory() { private final ReflectorFactory reflectorFactory = new BaseReflectorFactory() {
@ -233,27 +233,27 @@ public class TableInfo {
} }
public InsertListener getOnInsertListener() { public List<InsertListener> getOnInsertListener() {
return onInsertListener; return onInsertListener;
} }
public void setOnInsertListener(InsertListener onInsertListener) { public void setOnInsertListener(List<InsertListener> onInsertListener) {
this.onInsertListener = onInsertListener; this.onInsertListener = onInsertListener;
} }
public UpdateListener getOnUpdateListener() { public List<UpdateListener> getOnUpdateListener() {
return onUpdateListener; return onUpdateListener;
} }
public void setOnUpdateListener(UpdateListener onUpdateListener) { public void setOnUpdateListener(List<UpdateListener> onUpdateListener) {
this.onUpdateListener = onUpdateListener; this.onUpdateListener = onUpdateListener;
} }
public SetListener getOnSetListener() { public List<SetListener> getOnSetListener() {
return onSetListener; return onSetListener;
} }
public void setOnSetListener(SetListener onSetListener) { public void setOnSetListener(List<SetListener> onSetListener) {
this.onSetListener = onSetListener; this.onSetListener = onSetListener;
} }
@ -675,7 +675,7 @@ public class TableInfo {
Object rowValue = row.get(rowKey); Object rowValue = row.get(rowKey);
Object value = ConvertUtil.convert(rowValue, metaObject.getSetterType(columnInfo.property)); Object value = ConvertUtil.convert(rowValue, metaObject.getSetterType(columnInfo.property));
if (onSetListener != null) { if (onSetListener != null) {
value = onSetListener.onSet(instance, columnInfo.property, value); value = invokeOnSetListener(instance, columnInfo.getProperty(), value);
} }
metaObject.setValue(columnInfo.property, value); metaObject.setValue(columnInfo.property, value);
} }
@ -689,7 +689,7 @@ public class TableInfo {
Object rowValue = row.get(rowKey); Object rowValue = row.get(rowKey);
Object value = ConvertUtil.convert(rowValue, metaObject.getSetterType(columnInfo.property)); Object value = ConvertUtil.convert(rowValue, metaObject.getSetterType(columnInfo.property));
if (onSetListener != null) { if (onSetListener != null) {
value = onSetListener.onSet(instance, columnInfo.property, value); value = invokeOnSetListener(instance, columnInfo.getProperty(), value);
} }
metaObject.setValue(columnInfo.property, value); metaObject.setValue(columnInfo.property, value);
fillValue = true; fillValue = true;
@ -773,63 +773,49 @@ public class TableInfo {
public void invokeOnInsertListener(Object entity) { public void invokeOnInsertListener(Object entity) {
if (onInsertListener != null) { List<InsertListener> list = onInsertListener;
onInsertListener.onInsert(entity); if (list == null) {
return; list = new ArrayList<>();
} }
// 全局监听器
List<InsertListener> globalListeners = FlexGlobalConfig.getDefaultConfig().getSupportedInsertListener(entityClass);
InsertListener globalInsertListener = null; if (globalListeners != null) {
Class<?> registerClass = entityClass; list.addAll(globalListeners);
while (globalInsertListener == null && registerClass != Object.class && registerClass != null) {
globalInsertListener = FlexGlobalConfig.getDefaultConfig().getInsertListener(registerClass);
registerClass = registerClass.getSuperclass();
}
if (globalInsertListener != null) {
globalInsertListener.onInsert(entity);
} }
Collections.sort(list);
list.forEach(insertListener -> insertListener.onInsert(entity));
} }
public void invokeOnUpdateListener(Object entity) { public void invokeOnUpdateListener(Object entity) {
if (onUpdateListener != null) { List<UpdateListener> list = onUpdateListener;
onUpdateListener.onUpdate(entity); if (list == null) {
return; list = new ArrayList<>();
} }
// 全局监听器
UpdateListener globalUpdateListener = null; List<UpdateListener> globalListeners = FlexGlobalConfig.getDefaultConfig().getSupportedUpdateListener(entityClass);
Class<?> registerClass = entityClass; if (globalListeners != null) {
list.addAll(globalListeners);
while (globalUpdateListener == null && registerClass != Object.class && registerClass != null) {
globalUpdateListener = FlexGlobalConfig.getDefaultConfig().getUpdateListener(registerClass);
registerClass = registerClass.getSuperclass();
}
if (globalUpdateListener != null) {
globalUpdateListener.onUpdate(entity);
} }
Collections.sort(list);
list.forEach(insertListener -> insertListener.onUpdate(entity));
} }
public Object invokeOnSetListener(Object entity, String property, Object value) { public Object invokeOnSetListener(Object entity, String property, Object value) {
if (onSetListener != null) { List<SetListener> list = onSetListener;
return onSetListener.onSet(entity, property, value); if (list == null) {
list = new ArrayList<>();
} }
// 全局监听器
SetListener globalSetListener = null; List<SetListener> globalListeners = FlexGlobalConfig.getDefaultConfig().getSupportedSetListener(entityClass);
Class<?> registerClass = entityClass; if (globalListeners != null) {
list.addAll(globalListeners);
while (globalSetListener == null && registerClass != Object.class && registerClass != null) {
globalSetListener = FlexGlobalConfig.getDefaultConfig().getSetListener(registerClass);
registerClass = registerClass.getSuperclass();
} }
Collections.sort(list);
if (globalSetListener != null) { for (SetListener setListener : list) {
return globalSetListener.onSet(entity, property, value); value = setListener.onSet(entity, property, value);
} }
return value; return value;
} }
} }

View File

@ -42,6 +42,7 @@ import java.time.*;
import java.time.chrono.JapaneseDate; import java.time.chrono.JapaneseDate;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
public class TableInfoFactory { public class TableInfoFactory {
@ -120,16 +121,28 @@ public class TableInfoFactory {
tableInfo.setSchema(table.schema()); tableInfo.setSchema(table.schema());
tableInfo.setCamelToUnderline(table.camelToUnderline()); tableInfo.setCamelToUnderline(table.camelToUnderline());
if (table.onInsert() != NoneListener.class) { if (table.onInsert().length > 0) {
tableInfo.setOnInsertListener(ClassUtil.newInstance(table.onInsert())); List<InsertListener> insertListeners = Arrays.stream(table.onInsert())
.filter(listener -> listener != NoneListener.class)
.map(ClassUtil::newInstance)
.collect(Collectors.toList());
tableInfo.setOnInsertListener(insertListeners);
} }
if (table.onUpdate() != NoneListener.class) { if (table.onUpdate().length > 0) {
tableInfo.setOnUpdateListener(ClassUtil.newInstance(table.onUpdate())); List<UpdateListener> updateListeners = Arrays.stream(table.onUpdate())
.filter(listener -> listener != NoneListener.class)
.map(ClassUtil::newInstance)
.collect(Collectors.toList());
tableInfo.setOnUpdateListener(updateListeners);
} }
if (table.onSet() != NoneListener.class) { if (table.onSet().length > 0) {
tableInfo.setOnSetListener(ClassUtil.newInstance(table.onSet())); List<SetListener> setListeners = Arrays.stream(table.onSet())
.filter(listener -> listener != NoneListener.class)
.map(ClassUtil::newInstance)
.collect(Collectors.toList());
tableInfo.setOnSetListener(setListeners);
} }
if (StringUtil.isNotBlank(table.dataSource())) { if (StringUtil.isNotBlank(table.dataSource())) {

View File

@ -93,6 +93,12 @@
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>3.22.0</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -10,8 +10,8 @@ import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@Table(value = "tb_account",dataSource = "ds2",onSet = AccountOnSetListener.class) @Table(value = "tb_account", dataSource = "ds2", onSet = AccountOnSetListener.class)
public class Account extends BaseAccount implements Serializable { public class Account extends BaseAccount implements Serializable, AgeAware {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -26,7 +26,7 @@ public class Account extends BaseAccount implements Serializable {
@NotBlank @NotBlank
private Date birthday; private Date birthday;
@Column(typeHandler = Fastjson2TypeHandler.class,isLarge = true) @Column(typeHandler = Fastjson2TypeHandler.class, isLarge = true)
private Map<String, Object> options; private Map<String, Object> options;
@Column(isLogicDelete = true) @Column(isLogicDelete = true)
@ -49,10 +49,12 @@ public class Account extends BaseAccount implements Serializable {
this.userName = userName; this.userName = userName;
} }
@Override
public int getAge() { public int getAge() {
return age; return age;
} }
@Override
public void setAge(int age) { public void setAge(int age) {
this.age = age; this.age = age;
} }

View File

@ -0,0 +1,14 @@
package com.mybatisflex.test;
/**
* 有年龄的
*
* @author snow
* @since 2023/4/28
*/
public interface AgeAware {
void setAge(int age);
int getAge();
}

View File

@ -0,0 +1,28 @@
package com.mybatisflex.test;
import com.mybatisflex.annotation.InsertListener;
/**
* 年龄处理监听器
*
* @author snow
* @since 2023/4/28
*/
public class AgeHandleListener implements InsertListener {
@Override
public void onInsert(Object entity) {
if (entity instanceof AgeAware) {
AgeAware ageAware = (AgeAware) entity;
int age = ageAware.getAge();
if (age < 0) {
ageAware.setAge(0);
}
}
}
@Override
public int order() {
return 10;
}
}

View File

@ -0,0 +1,66 @@
package com.mybatisflex.test;
import com.mybatisflex.annotation.AbstractInsertListener;
import com.mybatisflex.core.FlexGlobalConfig;
import com.mybatisflex.core.MybatisFlexBootstrap;
import org.apache.ibatis.logging.stdout.StdOutImpl;
import org.assertj.core.api.WithAssertions;
import org.junit.Test;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import javax.sql.DataSource;
import java.util.Date;
/**
* 监听器测试
*
* @author snow
* @since 2023/4/28
*/
public class ListenerTest implements WithAssertions {
// 注册父类接口监听器
@Test
public void onInsertInterface() throws Exception {
DataSource dataSource = new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("schema.sql")
.build();
// 注册全局监听器
FlexGlobalConfig defaultConfig = FlexGlobalConfig.getDefaultConfig();
defaultConfig.registerInsertListener(new AgeHandleListener(), AgeAware.class);
defaultConfig.registerInsertListener(new AbstractInsertListener<AgeAware>() {
@Override
public Class<AgeAware> supportType() {
return AgeAware.class;
}
@Override
public void doInsert(AgeAware entity) {
entity.setAge(entity.getAge() + 1);
}
@Override
public int order() {
return 20;
}
}, Account.class);
MybatisFlexBootstrap bootstrap = MybatisFlexBootstrap.getInstance()
.setLogImpl(StdOutImpl.class)
.setDataSource(dataSource)
.addMapper(AccountMapper.class)
.start();
AccountMapper accountMapper = bootstrap.getMapper(AccountMapper.class);
Account account = new Account();
account.setAge(-2);
account.setUserName("on insert");
account.setBirthday(new Date());
accountMapper.insert(account);
Account one = accountMapper.selectOneById(account.getId());
assertThat(one.getAge()).isEqualTo(1);
}
}