MyBatis 主键生成策略(注解)拦截器

445 阅读2分钟

主键注解

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

@Target({ METHOD, FIELD })
@Retention(RUNTIME)
public @interface Id {

	Class<?> strategy() default UUIDGenerator.class;
}
public interface IdGenerator {

	public Serializable generator();
}
import ObjectId;

import java.io.Serializable;


public class UUIDGenerator implements IdGenerator {

    @Override
    public Serializable generator() {
        return new ObjectId().toString();
    }
}

注解解析

import java.io.Serializable;

import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;

public class PropertySet {

	private Set<ProPertyStrategyMapper> propertys = new HashSet<ProPertyStrategyMapper>();

	private Class<?> entity;

	@SuppressWarnings("unused")
	private PropertySet() {

	}

	public PropertySet(Class<?> entity) {
		this.entity = entity;
		this.build();
	}

	public Set<ProPertyStrategyMapper> getPropertys() {
		return propertys;
	}

	public void setPropertys(Set<ProPertyStrategyMapper> propertys) {
		this.propertys = propertys;
	}

	public PropertySet build() {
		Field[] fields = entity.getDeclaredFields();
		for (Field field : fields) {
			if ("serialVersionUID".equals(field.getName()))
				continue;

			//注解在属性上
			if(field.isAnnotationPresent(Id.class)){
				Id id = field.getAnnotation(Id.class);
				if (id.strategy() == null) {
					continue;
				}
				Class<?> generator = id.strategy();
				Object object = null;
				try {
					object = generator.newInstance();
				} catch (InstantiationException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				}
				if (!(object instanceof IdGenerator)) {
					continue;
				}
				IdGenerator idGenerator = (IdGenerator) object;
				ProPertyStrategyMapper proPertyStrategyMapper = new ProPertyStrategyMapper(field.getName(),
						idGenerator);
				propertys.add(proPertyStrategyMapper);
				break;
			}

			//注解在方法上
			PropertyDescriptor propertyDescriptor = null;
			try {
				propertyDescriptor = new PropertyDescriptor(field.getName(), entity);
			} catch (IntrospectionException e) {
				e.printStackTrace();
			}
			if (propertyDescriptor == null)
				continue;
			// 获取类的get方法
			Method method = propertyDescriptor.getReadMethod();
			if (method == null) {
				continue;
			}
			if (method.isAnnotationPresent(Id.class)) {
				Id id = method.getAnnotation(Id.class);
				if (id.strategy() == null) {
					continue;
				}
				Class<?> generator = id.strategy();
				Object object = null;
				try {
					object = generator.newInstance();
				} catch (InstantiationException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				}
				if (!(object instanceof IdGenerator)) {
					continue;
				}
				IdGenerator idGenerator = (IdGenerator) object;
				ProPertyStrategyMapper proPertyStrategyMapper = new ProPertyStrategyMapper(field.getName(),
						idGenerator);
				propertys.add(proPertyStrategyMapper);
				break;
			}
		}
		return this;
	}
}

策略映射

public class ProPertyStrategyMapper {

	private String propertyName;
	private IdGenerator generator;

	public ProPertyStrategyMapper(String propertyName, IdGenerator generator) {
		super();
		this.propertyName = propertyName;
		this.setGenerator(generator);
	}

	public String getPropertyName() {
		return propertyName;
	}

	public void setPropertyName(String propertyName) {
		this.propertyName = propertyName;
	}

	public IdGenerator getGenerator() {
		return generator;
	}

	public void setGenerator(IdGenerator generator) {
		this.generator = generator;
	}

}

拦截器

import ProPertyStrategyMapper;
import PropertySet;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.springframework.util.ReflectionUtils;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

@Intercepts({ @Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }) })
public class UUIDInterceptor implements Interceptor {

	@Override
	public Object intercept(Invocation invocation) throws Throwable {

		Object[] args = invocation.getArgs();
		if (args == null || args.length != 2 || !(args[0] instanceof MappedStatement)) {
			return invocation.proceed();
		}
		MappedStatement mappedStatement = (MappedStatement) args[0];
		SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
		if (!SqlCommandType.INSERT.equals(sqlCommandType)) {
			return invocation.proceed();
		}
		setDefultProperty(args[1]);
		return invocation.proceed();
	}

	public void setDefultProperty(Object obj) {
		// 批量插入
		if (obj instanceof Map) {
			Map<String, Object> map = (Map<String, Object>) obj;
			Set<String> keys = map.keySet();
			for (String key : keys) {
				List<Object> list = (List<Object>) map.get(key);
				for (Object object : list) {
					setObjectProperty(object);
				}
				break;
			}
			return;
		}
		setObjectProperty(obj);
	}

	@Override
	public Object plugin(Object target) {
		return Plugin.wrap(target, this);
	}

	@Override
	public void setProperties(Properties properties) {
		System.out.println("init UUIDInterceptor");
	}

	private void setObjectProperty(Object obj) {
		PropertySet propertySet = new PropertySet(obj.getClass());
		Set<ProPertyStrategyMapper> propers = propertySet.getPropertys();
		if (propers == null || propers.isEmpty())
			return;
		for (ProPertyStrategyMapper pro : propers)
			try {
				Field findField = ReflectionUtils.findField(obj.getClass(), pro.getPropertyName());
				findField.setAccessible(true);
				//findField.set(obj, pro.getGenerator().generator());
				ReflectionUtils.setField(findField, obj, pro.getGenerator().generator());
			} catch (Exception e) {
				e.printStackTrace();
			}
	}
}