提交 ff13c3e4 authored 作者:  狄熙卜's avatar 狄熙卜

替换example类的引用

上级 8d0aff2d
......@@ -11,7 +11,6 @@ import cn.gtmap.bdcdj.core.encrypt.adapter.encrypt.EmptyEncryptAdapter;
import cn.gtmap.bdcdj.core.encrypt.adapter.encrypt.EncryptAdapter;
import cn.gtmap.bdcdj.core.encrypt.adapter.encrypt.SimpleEncryptAdapter;
import cn.gtmap.bdcdj.core.encrypt.annotation.EncryptField;
import cn.gtmap.estateplat.core.support.mybatis.mapper.CommonMapper;
import org.apache.commons.lang3.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -48,7 +47,7 @@ public class EncryptAdapterBuilder {
return EMPTY_ENCRYPT_ADAPTER;
} else if (method != null && !ArrayUtils.isEmpty(method.getParameterTypes())) {
//优先确定是否是commonmapper,这种情况下不会有sql的配置,也不会有注解
if (method.getDeclaringClass().equals(CommonMapper.class)) {
if (method.getDeclaringClass().getName().contains("CommonMapper")) {
return new CommonEncryptAdapter(method, cryptProperties);
} else if (hasParamEncryptAnnotation(method)) {//如果参数上有注解,将参数加密
return new AnnotationEncryptAdapter(cryptProperties);
......@@ -66,7 +65,7 @@ public class EncryptAdapterBuilder {
if (!cryptProperties.isCryptEnable()) {
return EMPTY_DECRYPT_ADAPTER;
} else if (method != null && method.getReturnType() != Void.class) {
if (method.getDeclaringClass().equals(CommonMapper.class)) {
if (method.getDeclaringClass().getName().contains("CommonMapper")) {
return new CommonDecryptAdapter(this.entityClass, cryptProperties);
}else if(hasMethodEnctyptAnnotation(method)){
return new AnnotationDecryptAdapter(cryptProperties);
......
......@@ -5,7 +5,7 @@ import cn.gtmap.bdcdj.core.encrypt.LogicalOperatorEnum;
import cn.gtmap.bdcdj.core.encrypt.handler.CryptHandler;
import cn.gtmap.bdcdj.core.encrypt.handler.CryptHandlerFactory;
import cn.gtmap.bdcdj.core.encrypt.handler.ListCryptHandler;
import cn.gtmap.estateplat.core.support.mybatis.mapper.Example;
import cn.gtmap.bdcdj.core.mybatisMapper.entity.Example;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
......
package cn.gtmap.bdcdj.core.exception;
/**
*
* @author jane
* @date 14-1-7
*/
public class BdcdjException extends RuntimeException{
public BdcdjException() {
super();
}
/**
* @param msg
*/
public BdcdjException(String msg){
super(msg);
}
/**
* @param cause
*/
public BdcdjException(Throwable cause) {
super(cause);
}
}
package cn.gtmap.bdcdj.core.mybatisMapper.entity;
import cn.gtmap.bdcdj.core.exception.BdcdjException;
import cn.gtmap.bdcdj.core.mybatisMapper.mapperhelper.EntityHelper;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 通用的Example查询对象
*
* @author liuzh
*/
public class Example {
protected String orderByClause;
protected boolean distinct;
protected boolean exists;
protected List<Criteria> oredCriteria;
protected Class<?> entityClass;
protected EntityHelper.EntityTable table;
//属性和列对应
protected Map<String, EntityHelper.EntityColumn> propertyMap;
/**
* 默认exists为true
*
* @param entityClass
*/
public Example(Class<?> entityClass) {
this(entityClass, true);
}
/**
* 带exists参数的构造方法
*
* @param entityClass
* @param exists - true时,如果字段不存在就抛出异常,false时,如果不存在就不使用该字段的条件
*/
public Example(Class<?> entityClass, boolean exists) {
this.exists = exists;
oredCriteria = new ArrayList<Criteria>();
this.entityClass = entityClass;
table = EntityHelper.getEntityTable(entityClass);
propertyMap = new HashMap<String, EntityHelper.EntityColumn>(table.getEntityClassColumns().size());
for (EntityHelper.EntityColumn column : table.getEntityClassColumns()) {
propertyMap.put(column.getProperty(), column);
}
}
public Class<?> getEntityClass() {
return entityClass;
}
public void setOrderByClause(String orderByClause) {
this.orderByClause = orderByClause;
}
public String getOrderByClause() {
return orderByClause;
}
public void setDistinct(boolean distinct) {
this.distinct = distinct;
}
public boolean isDistinct() {
return distinct;
}
public List<Criteria> getOredCriteria() {
return oredCriteria;
}
public void or(Criteria criteria) {
oredCriteria.add(criteria);
}
public Criteria or() {
Criteria criteria = createCriteriaInternal();
oredCriteria.add(criteria);
return criteria;
}
public Criteria createCriteria() {
Criteria criteria = createCriteriaInternal();
if (oredCriteria.size() == 0) {
oredCriteria.add(criteria);
}
return criteria;
}
protected Criteria createCriteriaInternal() {
Criteria criteria = new Criteria(propertyMap, exists);
return criteria;
}
public void clear() {
oredCriteria.clear();
orderByClause = null;
distinct = false;
}
protected abstract static class GeneratedCriteria {
protected List<Criterion> criteria;
//字段是否必须存在
protected boolean exists;
//属性和列对应
protected Map<String, EntityHelper.EntityColumn> propertyMap;
protected GeneratedCriteria(Map<String, EntityHelper.EntityColumn> propertyMap) {
this(propertyMap, true);
}
protected GeneratedCriteria(Map<String, EntityHelper.EntityColumn> propertyMap, boolean exists) {
super();
this.exists = exists;
criteria = new ArrayList<Criterion>();
this.propertyMap = propertyMap;
}
private String column(String property) {
if (propertyMap.containsKey(property)) {
return propertyMap.get(property).getColumn();
} else if (exists) {
throw new BdcdjException("当前实体类不包含名为" + property + "的属性!");
} else {
return null;
}
}
private String property(String property) {
if (propertyMap.containsKey(property)) {
return property;
} else if (exists) {
throw new BdcdjException("当前实体类不包含名为" + property + "的属性!");
} else {
return null;
}
}
public boolean isValid() {
return criteria.size() > 0;
}
public List<Criterion> getAllCriteria() {
return criteria;
}
public List<Criterion> getCriteria() {
return criteria;
}
protected void addCriterion(String condition) {
if (condition == null) {
throw new BdcdjException("Value for condition cannot be null");
}
if (condition.startsWith("null")) {
return;
}
criteria.add(new Criterion(condition));
}
protected void addCriterion(String condition, Object value, String property) {
if (value == null) {
throw new BdcdjException("Value for " + property + " cannot be null");
}
if (property == null) {
return;
}
criteria.add(new Criterion(condition, value));
}
protected void addCriterion(String condition, Object value1, Object value2, String property) {
if (value1 == null || value2 == null) {
throw new BdcdjException("Between values for " + property + " cannot be null");
}
if (property == null) {
return;
}
criteria.add(new Criterion(condition, value1, value2));
}
public Criteria andIsNull(String property) {
addCriterion(column(property) + " is null");
return (Criteria) this;
}
public Criteria andIsNotNull(String property) {
addCriterion(column(property) + " is not null");
return (Criteria) this;
}
public Criteria andEqualTo(String property, Object value) {
addCriterion(column(property) + " =", value, property(property));
return (Criteria) this;
}
public Criteria andEqualNvlTo(String property, Object value1,Object value2) {
addCriterion("nvl("+column(property)+",'"+value2+"')" + " =", value1, property(property));
return (Criteria) this;
}
public Criteria andNotEqualTo(String property, Object value) {
addCriterion(column(property) + " <>", value, property(property));
return (Criteria) this;
}
public Criteria andNotEqualNvlTo(String property, Object value1,Object value2) {
addCriterion("nvl("+column(property)+",'"+value2+"')" + " <>", value1, property(property));
return (Criteria) this;
}
public Criteria andGreaterThan(String property, Object value) {
addCriterion(column(property) + " >", value, property(property));
return (Criteria) this;
}
public Criteria andGreaterThanOrEqualTo(String property, Object value) {
addCriterion(column(property) + " >=", value, property(property));
return (Criteria) this;
}
public Criteria andLessThan(String property, Object value) {
addCriterion(column(property) + " <", value, property(property));
return (Criteria) this;
}
public Criteria andLessThanOrEqualTo(String property, Object value) {
addCriterion(column(property) + " <=", value, property(property));
return (Criteria) this;
}
public Criteria andIn(String property, List<Object> values) {
addCriterion(column(property) + " in", values, property(property));
return (Criteria) this;
}
public Criteria andNotIn(String property, List<Object> values) {
addCriterion(column(property) + " not in", values, property(property));
return (Criteria) this;
}
public Criteria andBetween(String property, Object value1, Object value2) {
addCriterion(column(property) + " between", value1, value2, property(property));
return (Criteria) this;
}
public Criteria andNotBetween(String property, Object value1, Object value2) {
addCriterion(column(property) + " not between", value1, value2, property(property));
return (Criteria) this;
}
public Criteria andLike(String property, String value) {
addCriterion(column(property) + " like", value, property(property));
return (Criteria) this;
}
public Criteria andNotLike(String property, String value) {
addCriterion(column(property) + " not like", value, property(property));
return (Criteria) this;
}
}
public static class Criteria extends GeneratedCriteria {
protected Criteria(Map<String, EntityHelper.EntityColumn> propertyMap) {
super(propertyMap);
}
protected Criteria(Map<String, EntityHelper.EntityColumn> propertyMap, boolean exists) {
super(propertyMap, exists);
}
}
public static class Criterion {
private String condition;
private Object value;
private Object secondValue;
private boolean noValue;
private boolean singleValue;
private boolean betweenValue;
private boolean listValue;
private String typeHandler;
public String getCondition() {
return condition;
}
public Object getValue() {
return value;
}
public Object getSecondValue() {
return secondValue;
}
public boolean isNoValue() {
return noValue;
}
public boolean isSingleValue() {
return singleValue;
}
public boolean isBetweenValue() {
return betweenValue;
}
public boolean isListValue() {
return listValue;
}
public String getTypeHandler() {
return typeHandler;
}
protected Criterion(String condition) {
super();
this.condition = condition;
this.typeHandler = null;
this.noValue = true;
}
protected Criterion(String condition, Object value, String typeHandler) {
super();
this.condition = condition;
this.value = value;
this.typeHandler = typeHandler;
if (value instanceof List<?>) {
this.listValue = true;
} else {
this.singleValue = true;
}
}
protected Criterion(String condition, Object value) {
this(condition, value, null);
}
protected Criterion(String condition, Object value, Object secondValue, String typeHandler) {
super();
this.condition = condition;
this.value = value;
this.secondValue = secondValue;
this.typeHandler = typeHandler;
this.betweenValue = true;
}
protected Criterion(String condition, Object value, Object secondValue) {
this(condition, value, secondValue, null);
}
}
}
\ No newline at end of file
/*
* The MIT License (MIT)
*
* Copyright (c) 2014 abel533@gmail.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package cn.gtmap.bdcdj.core.mybatisMapper.mapperhelper;
import cn.gtmap.bdcdj.core.exception.BdcdjException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OrderBy;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Transient;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* 实体类工具类 - 处理实体和数据库表以及字段关键的一个类
* <p/>
* <p>项目地址 : <a href="https://github.com/abel533/Mapper" target="_blank">https://github.com/abel533/Mapper</a></p>
*
* @author liuzh
*/
public class EntityHelper {
private static final Logger LOGGER = LoggerFactory.getLogger(EntityHelper.class);
/**
* 实体对应表的配置信息
*/
public static class EntityTable {
private String name;
private String catalog;
private String schema;
//实体类 => 全部列属性
private Set<EntityColumn> entityClassColumns;
//实体类 => 主键信息
private Set<EntityColumn> entityClassPKColumns;
//字段名和属性名的映射
private Map<String, String> aliasMap;
public void setTable(Table table) {
this.name = table.name();
this.catalog = table.catalog();
this.schema = table.schema();
}
public String getName() {
return name;
}
public String getCatalog() {
return catalog;
}
public String getSchema() {
return schema;
}
public String getPrefix() {
if (catalog != null && catalog.length() > 0) {
return catalog;
}
if (schema != null && schema.length() > 0) {
return catalog;
}
return "";
}
public Set<EntityColumn> getEntityClassColumns() {
return entityClassColumns;
}
public Set<EntityColumn> getEntityClassPKColumns() {
return entityClassPKColumns;
}
public Map<String, String> getAliasMap() {
return aliasMap;
}
}
/**
* 实体字段对应数据库列的信息
*/
public static class EntityColumn {
private String property;
private String column;
private Class<?> javaType;
private String sequenceName;
private boolean id = false;
private boolean uuid = false;
private boolean identity = false;
private String generator;
private String orderBy;
public String getProperty() {
return property;
}
public void setProperty(String property) {
this.property = property;
}
public String getColumn() {
return column;
}
public void setColumn(String column) {
this.column = column;
}
public Class<?> getJavaType() {
return javaType;
}
public void setJavaType(Class<?> javaType) {
this.javaType = javaType;
}
public String getSequenceName() {
return sequenceName;
}
public void setSequenceName(String sequenceName) {
this.sequenceName = sequenceName;
}
public boolean isId() {
return id;
}
public void setId(boolean id) {
this.id = id;
}
public boolean isUuid() {
return uuid;
}
public void setUuid(boolean uuid) {
this.uuid = uuid;
}
public boolean isIdentity() {
return identity;
}
public void setIdentity(boolean identity) {
this.identity = identity;
}
public String getGenerator() {
return generator;
}
public void setGenerator(String generator) {
this.generator = generator;
}
public String getOrderBy() {
return orderBy;
}
public void setOrderBy(String orderBy) {
this.orderBy = orderBy;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
EntityColumn that = (EntityColumn) o;
if (id != that.id) {
return false;
}
if (identity != that.identity) {
return false;
}
if (uuid != that.uuid) {
return false;
}
if (column != null ? !column.equals(that.column) : that.column != null) {
return false;
}
if (generator != null ? !generator.equals(that.generator) : that.generator != null) {
return false;
}
if (javaType != null ? !javaType.equals(that.javaType) : that.javaType != null) {
return false;
}
if (orderBy != null ? !orderBy.equals(that.orderBy) : that.orderBy != null) {
return false;
}
if (property != null ? !property.equals(that.property) : that.property != null) {
return false;
}
if (sequenceName != null ? !sequenceName.equals(that.sequenceName) : that.sequenceName != null) {
return false;
}
return true;
}
@Override
public int hashCode() {
int result = property != null ? property.hashCode() : 0;
result = 31 * result + (column != null ? column.hashCode() : 0);
result = 31 * result + (javaType != null ? javaType.hashCode() : 0);
result = 31 * result + (sequenceName != null ? sequenceName.hashCode() : 0);
result = 31 * result + (id ? 1 : 0);
result = 31 * result + (uuid ? 1 : 0);
result = 31 * result + (identity ? 1 : 0);
result = 31 * result + (generator != null ? generator.hashCode() : 0);
result = 31 * result + (orderBy != null ? orderBy.hashCode() : 0);
return result;
}
}
/**
* 实体类 => 表对象
*/
private static final Map<Class<?>, EntityTable> entityTableMap = new HashMap<Class<?>, EntityTable>();
/**
* 获取表对象
*
* @param entityClass
* @return
*/
public static EntityTable getEntityTable(Class<?> entityClass) {
EntityTable entityTable = entityTableMap.get(entityClass);
if (entityTable == null) {
initEntityNameMap(entityClass);
entityTable = entityTableMap.get(entityClass);
}
if (entityTable == null) {
throw new BdcdjException("无法获取实体类" + entityClass.getCanonicalName() + "对应的表名!");
}
return entityTable;
}
/**
* 获取全部列
*
* @param entityClass
* @return
*/
public static Set<EntityColumn> getColumns(Class<?> entityClass) {
return getEntityTable(entityClass).getEntityClassColumns();
}
/**
* 获取主键信息
*
* @param entityClass
* @return
*/
public static Set<EntityColumn> getPKColumns(Class<?> entityClass) {
return getEntityTable(entityClass).getEntityClassPKColumns();
}
/**
* 获取字段映射关系
*
* @param entityClass
* @return
*/
public static Map<String, String> getColumnAlias(Class<?> entityClass) {
EntityTable entityTable = getEntityTable(entityClass);
if (entityTable.aliasMap != null) {
return entityTable.aliasMap;
}
Set<EntityColumn> columnList = entityTable.getEntityClassColumns();
entityTable.aliasMap = new HashMap<String, String>(columnList.size());
for (EntityColumn column : columnList) {
entityTable.aliasMap.put(column.getColumn(), column.getProperty());
}
return entityTable.aliasMap;
}
/**
* 获取查询的Select
*
* @param entityClass
* @return
*/
public static String getSelectColumns(Class<?> entityClass) {
Set<EntityColumn> columnList = getColumns(entityClass);
StringBuilder selectBuilder = new StringBuilder();
boolean skipAlias = Map.class.isAssignableFrom(entityClass);
for (EntityColumn entityColumn : columnList) {
selectBuilder.append(entityColumn.getColumn());
if (!skipAlias && !entityColumn.getColumn().equalsIgnoreCase(entityColumn.getProperty())) {
selectBuilder.append(" ").append(entityColumn.getProperty().toUpperCase()).append(",");
} else {
selectBuilder.append(",");
}
}
return selectBuilder.substring(0, selectBuilder.length() - 1);
}
/**
* 获取查询的Select
*
* @param entityClass
* @return
*/
public static String getAllColumns(Class<?> entityClass) {
Set<EntityColumn> columnList = getColumns(entityClass);
StringBuilder selectBuilder = new StringBuilder();
for (EntityColumn entityColumn : columnList) {
selectBuilder.append(entityColumn.getColumn()).append(",");
}
return selectBuilder.substring(0, selectBuilder.length() - 1);
}
/**
* 获取主键的Where语句
*
* @param entityClass
* @return
*/
public static String getPrimaryKeyWhere(Class<?> entityClass) {
Set<EntityColumn> entityColumns = getPKColumns(entityClass);
StringBuilder whereBuilder = new StringBuilder();
for (EntityColumn column : entityColumns) {
whereBuilder.append(column.getColumn()).append(" = ?").append(" AND ");
}
return whereBuilder.substring(0, whereBuilder.length() - 4);
}
/**
* 初始化实体属性
*
* @param entityClass
*/
public static synchronized void initEntityNameMap(Class<?> entityClass) {
if (entityTableMap.get(entityClass) != null) {
return;
}
//表名
EntityTable entityTable = null;
if (entityClass.isAnnotationPresent(Table.class)) {
Table table = entityClass.getAnnotation(Table.class);
if (!"".equals(table.name())) {
entityTable = new EntityTable();
entityTable.setTable(table);
}
}
if (entityTable == null) {
entityTable = new EntityTable();
entityTable.name = camelhumpToUnderline(entityClass.getSimpleName()).toUpperCase();
}
//列
List<Field> fieldList = getAllField(entityClass, null);
Set<EntityColumn> columnSet = new HashSet<EntityColumn>();
Set<EntityColumn> pkColumnSet = new HashSet<EntityColumn>();
for (Field field : fieldList) {
//排除字段
if (field.isAnnotationPresent(Transient.class)) {
continue;
}
//排除字段 注意版本判读有非号
// if (field.isAnnotationPresent(CityAttr.class)) {
// // 转换为list
// List<String> tempList = Arrays.asList(field.getAnnotation(CityAttr.class).city());
// // 利用list的包含方法,进行判断
// if (!tempList.contains(SysVersions.getCurrentSysVersion())) {
// continue;
// }
// }
EntityColumn entityColumn = new EntityColumn();
if (field.isAnnotationPresent(Id.class)) {
entityColumn.setId(true);
}
String columnName = null;
if (field.isAnnotationPresent(Column.class)) {
Column column = field.getAnnotation(Column.class);
columnName = column.name();
}
if (columnName == null || "".equals(columnName)) {
columnName = camelhumpToUnderline(field.getName());
}
entityColumn.setProperty(field.getName());
entityColumn.setColumn(columnName.toUpperCase());
entityColumn.setJavaType(field.getType());
//order by
if (field.isAnnotationPresent(OrderBy.class)) {
OrderBy orderBy = field.getAnnotation(OrderBy.class);
if ("".equals(orderBy.value())) {
entityColumn.setOrderBy("ASC");
} else {
entityColumn.setOrderBy(orderBy.value());
}
}
//主键策略 - Oracle序列,MySql自动增长,UUID
if (field.isAnnotationPresent(SequenceGenerator.class)) {
SequenceGenerator sequenceGenerator = field.getAnnotation(SequenceGenerator.class);
if ("".equals(sequenceGenerator.sequenceName())) {
throw new BdcdjException(entityClass + "字段" + field.getName() + "的注解@SequenceGenerator未指定sequenceName!");
}
entityColumn.setSequenceName(sequenceGenerator.sequenceName());
} else if (field.isAnnotationPresent(GeneratedValue.class)) {
GeneratedValue generatedValue = field.getAnnotation(GeneratedValue.class);
if ("UUID".equals(generatedValue.generator())) {
if (field.getType().equals(String.class)) {
entityColumn.setUuid(true);
} else {
throw new BdcdjException(field.getName() + " - 该字段@GeneratedValue配置为UUID,但该字段类型不是String");
}
} else if ("JDBC".equals(generatedValue.generator())) {
if (Number.class.isAssignableFrom(field.getType())) {
entityColumn.setIdentity(true);
entityColumn.setGenerator("JDBC");
} else {
throw new BdcdjException(field.getName() + " - 该字段@GeneratedValue配置为UUID,但该字段类型不是String");
}
} else {
//允许通过generator来设置获取id的sql,例如mysql=CALL IDENTITY(),hsqldb=SELECT SCOPE_IDENTITY()
//允许通过拦截器参数设置公共的generator
if (generatedValue.strategy() == GenerationType.IDENTITY) {
//mysql的自动增长
entityColumn.setIdentity(true);
if (!"".equals(generatedValue.generator())) {
String generator = null;
MapperHelper.IdentityDialect identityDialect = MapperHelper.IdentityDialect.getDatabaseDialect(generatedValue.generator());
if (identityDialect != null) {
generator = identityDialect.getIdentityRetrievalStatement();
} else {
generator = generatedValue.generator();
}
entityColumn.setGenerator(generator);
}
} else {
throw new BdcdjException(field.getName()
+ " - 该字段@GeneratedValue配置只允许以下几种形式:" +
"\n1.全部数据库通用的@GeneratedValue(generator=\"UUID\")" +
"\n2.useGeneratedKeys的@GeneratedValue(generator=\\\"JDBC\\\") " +
"\n3.类似mysql数据库的@GeneratedValue(strategy=GenerationType.IDENTITY[,generator=\"Mysql\"])");
}
}
}
columnSet.add(entityColumn);
if (entityColumn.isId()) {
pkColumnSet.add(entityColumn);
}
}
entityTable.entityClassColumns = columnSet;
if (pkColumnSet.size() == 0) {
entityTable.entityClassPKColumns = columnSet;
} else {
entityTable.entityClassPKColumns = pkColumnSet;
}
//缓存
entityTableMap.put(entityClass, entityTable);
}
public static void main(String[] args) {
}
/**
* 将驼峰风格替换为下划线风格
*/
public static String camelhumpToUnderline(String str) {
final int size;
final char[] chars;
final StringBuilder sb = new StringBuilder(
(size = (chars = str.toCharArray()).length) * 3 / 2 + 1);
char c;
for (int i = 0; i < size; i++) {
c = chars[i];
if (isUppercaseAlpha(c)) {
sb.append('_').append(c);
} else {
sb.append(toUpperAscii(c));
}
}
return sb.charAt(0) == '_' ? sb.substring(1) : sb.toString();
}
public static boolean isUppercaseAlpha(char c) {
return (c >= 'A') && (c <= 'Z');
}
public static char toUpperAscii(char c) {
if (isUppercaseAlpha(c)) {
c -= (char) 0x20;
}
return c;
}
/**
* 获取全部的Field
*
* @param entityClass
* @param fieldList
* @return
*/
private static List<Field> getAllField(Class<?> entityClass, List<Field> fieldList) {
if (fieldList == null) {
fieldList = new ArrayList<Field>();
}
if (entityClass.equals(Object.class)) {
return fieldList;
}
Field[] fields = entityClass.getDeclaredFields();
for (Field field : fields) {
//排除静态字段,解决bug#2
if (!Modifier.isStatic(field.getModifiers())) {
fieldList.add(field);
}
}
Class<?> superClass = entityClass.getSuperclass();
if (superClass != null
&& !superClass.equals(Object.class)
&& (superClass.isAnnotationPresent(Entity.class)
|| (!Map.class.isAssignableFrom(superClass)
&& !Collection.class.isAssignableFrom(superClass)))) {
return getAllField(entityClass.getSuperclass(), fieldList);
}
return fieldList;
}
/**
* map转换为Map
*
* @param map
* @param beanClass
* @return
*/
public static Map<String, Object> map2AliasMap(Map<String, Object> map, Class<?> beanClass) {
if (map == null) {
return null;
}
Map<String, String> alias = getColumnAlias(beanClass);
Map<String, Object> result = new HashMap<String, Object>();
for (String name : map.keySet()) {
String alia = name;
//sql在被其他拦截器处理后,字段可能发生变化,例如分页插件增加rownum
if (alias.containsKey(name)) {
alia = alias.get(name);
}
result.put(alia, map.get(name));
}
return result;
}
/**
* map转换为bean
*
* @param map
* @param beanClass
* @return
*//*
public static Object map2Bean(Map<String, Object> map, Class<?> beanClass) {
try {
if (map == null) {
return null;
}
Map<String, Object> aliasMap = map2AliasMap(map, beanClass);
Object bean = beanClass.newInstance();
BeanUtilsEx.copyProperties(bean, aliasMap);
return bean;
} catch (InstantiationException e) {
LOGGER.error("", e);
throw new BdcdjException(beanClass.getCanonicalName() + "类没有默认空的构造方法!");
} catch (Exception e) {
throw new BdcdjException(e);
}
}
*//**
* mapList转换为beanList
*
* @param mapList
* @param beanClass
* @return
*//*
public static List<?> maplist2BeanList(List<?> mapList, Class<?> beanClass) {
if (mapList == null || mapList.size() == 0) {
return null;
}
List list = new ArrayList<Object>(mapList.size());
for (Object map : mapList) {
list.add(map2Bean((Map) map, beanClass));
}
mapList.clear();
mapList.addAll(list);
return mapList;
}*/
}
\ No newline at end of file
/*
* The MIT License (MIT)
*
* Copyright (c) 2014 abel533@gmail.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package cn.gtmap.bdcdj.core.mybatisMapper.mapperhelper;
import cn.gtmap.bdcdj.core.exception.BdcdjException;
import org.apache.ibatis.annotations.DeleteProvider;
import org.apache.ibatis.annotations.InsertProvider;
import org.apache.ibatis.annotations.SelectProvider;
import org.apache.ibatis.annotations.UpdateProvider;
import org.apache.ibatis.builder.annotation.ProviderSqlSource;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
/**
* 处理主要逻辑,最关键的一个类
*
* <p>项目地址 : <a href="https://github.com/abel533/Mapper" target="_blank">https://github.com/abel533/Mapper</a></p>
*
* @author liuzh
*/
public class MapperHelper {
private static final Logger LOGGER = LoggerFactory.getLogger(MapperHelper.class);
/**
* 注册的通用Mapper接口
*/
private Map<Class<?>, MapperTemplate> registerMapper = new HashMap<Class<?>, MapperTemplate>();
/**
* 缓存msid和MapperTemplate
*/
private Map<String, MapperTemplate> msIdCache = new HashMap<String, MapperTemplate>();
/**
* 缓存skip结果
*/
private final Map<String, Boolean> msIdSkip = new HashMap<String, Boolean>();
/**
* 缓存已经处理过的Collection<MappedStatement>
*/
private Set<Collection<MappedStatement>> collectionSet = new HashSet<Collection<MappedStatement>>();
/**
* 是否使用的Spring
*/
private boolean spring = false;
/**
* 是否为Spring4.x以上版本
*/
private boolean spring4 = false;
/**
* Spring版本号
*/
private String springVersion;
/**
* 对于一般的getAllIfColumnNode,是否判断!='',默认不判断
*/
private boolean notEmpty = false;
/**
* 默认构造方法
*/
public MapperHelper() {
}
/**
* 带配置的构造方法
*
* @param properties
*/
public MapperHelper(Properties properties) {
setProperties(properties);
}
/**
* 缓存初始化时的SqlSession
*/
private List<SqlSession> sqlSessions = new ArrayList<SqlSession>();
/**
* 针对Spring注入需要处理的SqlSession
*
* @param sqlSessions
*/
public void setSqlSessions(SqlSession[] sqlSessions) {
if (sqlSessions != null && sqlSessions.length > 0) {
this.sqlSessions.addAll(Arrays.asList(sqlSessions));
}
}
public boolean isNotEmpty() {
return notEmpty;
}
public void setNotEmpty(boolean notEmpty) {
this.notEmpty = notEmpty;
}
/**
* Spring初始化方法,使用Spring时需要配置init-method="initMapper"
*/
public void initMapper() {
//只有Spring会执行这个方法,所以Spring配置的时候,从这儿可以尝试获取Spring的版本
//先判断Spring版本,对下面的操作有影响
//Spring4以上支持泛型注入,因此可以扫描通用Mapper
initSpringVersion();
for (SqlSession sqlSession : sqlSessions) {
processConfiguration(sqlSession.getConfiguration());
}
}
/**
* 检测Spring版本号,Spring4.x以上支持泛型注入
*/
private void initSpringVersion() {
try {
//反射获取SpringVersion
Class<?> springVersionClass = Class.forName("org.springframework.core.SpringVersion");
springVersion = (String) springVersionClass.getDeclaredMethod("getVersion", new Class<?>[0]).invoke(null, new Object[0]);
spring = true;
if (springVersion.indexOf(".") > 0) {
int MajorVersion = Integer.parseInt(springVersion.substring(0, springVersion.indexOf(".")));
if (MajorVersion > 3) {
spring4 = true;
} else {
spring4 = false;
}
}
} catch (Exception e) {
LOGGER.error("", e);
spring = false;
spring4 = false;
}
}
/**
* 是否为Spring4.x以上版本
*
* @return
*/
public boolean isSpring4() {
return spring4;
}
/**
* 是否为Spring4.x以上版本
*
* @return
*/
public boolean isSpring() {
return spring;
}
/**
* 获取Spring版本号
*
* @return
*/
public String getSpringVersion(){
return springVersion;
}
/**
* 通过通用Mapper接口获取对应的MapperTemplate
*
* @param mapperClass
* @return
* @throws Exception
*/
private MapperTemplate fromMapperClass(Class<?> mapperClass) {
Method[] methods = mapperClass.getDeclaredMethods();
Class<?> templateClass = null;
Class<?> tempClass = null;
Set<String> methodSet = new HashSet<String>();
for (Method method : methods) {
if (method.isAnnotationPresent(SelectProvider.class)) {
SelectProvider provider = method.getAnnotation(SelectProvider.class);
tempClass = provider.type();
methodSet.add(method.getName());
} else if (method.isAnnotationPresent(InsertProvider.class)) {
InsertProvider provider = method.getAnnotation(InsertProvider.class);
tempClass = provider.type();
methodSet.add(method.getName());
} else if (method.isAnnotationPresent(DeleteProvider.class)) {
DeleteProvider provider = method.getAnnotation(DeleteProvider.class);
tempClass = provider.type();
methodSet.add(method.getName());
} else if (method.isAnnotationPresent(UpdateProvider.class)) {
UpdateProvider provider = method.getAnnotation(UpdateProvider.class);
tempClass = provider.type();
methodSet.add(method.getName());
}
if (templateClass == null) {
templateClass = tempClass;
} else if (templateClass != tempClass) {
throw new BdcdjException("一个通用Mapper中只允许存在一个MapperTemplate子类!");
}
}
if (templateClass == null || !MapperTemplate.class.isAssignableFrom(templateClass)) {
throw new BdcdjException("接口中不存在包含type为MapperTemplate的Provider注解,这不是一个合法的通用Mapper接口类!");
}
MapperTemplate mapperTemplate = null;
try {
mapperTemplate = (MapperTemplate) templateClass.getConstructor(Class.class, MapperHelper.class).newInstance(mapperClass, this);
} catch (Exception e) {
LOGGER.debug("", e);
throw new BdcdjException("实例化MapperTemplate对象失败:" + e.getMessage());
}
//注册方法
for (String methodName : methodSet) {
try {
mapperTemplate.addMethodMap(methodName, templateClass.getMethod(methodName, MappedStatement.class));
} catch (NoSuchMethodException e) {
LOGGER.debug("", e);
throw new BdcdjException(templateClass.getCanonicalName() + "中缺少" + methodName + "方法!");
}
}
return mapperTemplate;
}
/**
* 注册通用Mapper接口
*
* @param mapperClass
* @throws Exception
*/
public void registerMapper(Class<?> mapperClass) {
if (registerMapper.get(mapperClass) == null) {
registerMapper.put(mapperClass, fromMapperClass(mapperClass));
} else {
throw new BdcdjException("已经注册过的通用Mapper[" + mapperClass.getCanonicalName() + "]不能多次注册!");
}
}
/**
* 注册通用Mapper接口
*
* @param mapperClass
* @throws Exception
*/
public void registerMapper(String mapperClass) {
try {
registerMapper(Class.forName(mapperClass));
} catch (ClassNotFoundException e) {
LOGGER.error("", e);
throw new BdcdjException("注册通用Mapper[" + mapperClass + "]失败,找不到该通用Mapper!");
}
}
/**
* 方便Spring注入
*
* @param mappers
*/
public void setMappers(String[] mappers) {
if (mappers != null && mappers.length > 0) {
for (String mapper : mappers) {
registerMapper(mapper);
}
}
}
/**
* IDENTITY的可选值
*/
public enum IdentityDialect {
DB2("VALUES IDENTITY_VAL_LOCAL()"),
MYSQL("SELECT LAST_INSERT_ID()"),
SQLSERVER("SELECT SCOPE_IDENTITY()"),
CLOUDSCAPE("VALUES IDENTITY_VAL_LOCAL()"),
DERBY("VALUES IDENTITY_VAL_LOCAL()"),
HSQLDB("CALL IDENTITY()"),
SYBASE("SELECT @@IDENTITY"),
DB2_MF("SELECT IDENTITY_VAL_LOCAL() FROM SYSIBM.SYSDUMMY1"),
INFORMIX("select dbinfo('sqlca.sqlerrd1') from systables where tabid=1");
private String identityRetrievalStatement;
private IdentityDialect(String identityRetrievalStatement) {
this.identityRetrievalStatement = identityRetrievalStatement;
}
public String getIdentityRetrievalStatement() {
return identityRetrievalStatement;
}
public static IdentityDialect getDatabaseDialect(String database) {
IdentityDialect returnValue = null;
if ("DB2".equalsIgnoreCase(database)) {
returnValue = DB2;
} else if ("MySQL".equalsIgnoreCase(database)) {
returnValue = MYSQL;
} else if ("SqlServer".equalsIgnoreCase(database)) {
returnValue = SQLSERVER;
} else if ("Cloudscape".equalsIgnoreCase(database)) {
returnValue = CLOUDSCAPE;
} else if ("Derby".equalsIgnoreCase(database)) {
returnValue = DERBY;
} else if ("HSQLDB".equalsIgnoreCase(database)) {
returnValue = HSQLDB;
} else if ("SYBASE".equalsIgnoreCase(database)) {
returnValue = SYBASE;
} else if ("DB2_MF".equalsIgnoreCase(database)) {
returnValue = DB2_MF;
} else if ("Informix".equalsIgnoreCase(database)) {
returnValue = INFORMIX;
}
return returnValue;
}
}
//基础可配置项
private class Config {
private String UUID;
private String IDENTITY;
private boolean BEFORE = false;
private String seqFormat;
private String catalog;
private String schema;
}
private Config config = new Config();
/**
* 设置UUID生成策略
* <br>配置UUID生成策略需要使用OGNL表达式
* <br>默认值32位长度:@java.util.UUID@randomUUID().toString().replace("-", "")
*
* @param UUID
*/
public void setUUID(String UUID) {
config.UUID = UUID;
}
/**
* 主键自增回写方法,默认值MYSQL,详细说明请看文档
*
* @param IDENTITY
*/
public void setIDENTITY(String IDENTITY) {
IdentityDialect identityDialect = IdentityDialect.getDatabaseDialect(IDENTITY);
if (identityDialect != null) {
config.IDENTITY = identityDialect.getIdentityRetrievalStatement();
} else {
config.IDENTITY = IDENTITY;
}
}
/**
* 主键自增回写方法执行顺序,默认AFTER,可选值为(BEFORE|AFTER)
*
* @param order
*/
public void setOrder(String order) {
config.BEFORE = "BEFORE".equalsIgnoreCase(order);
}
/**
* 序列的获取规则,使用{num}格式化参数,默认值为{0}.nextval,针对Oracle
* <br>可选参数一共3个,对应0,1,2,分别为SequenceName,ColumnName, PropertyName
*
* @param seqFormat
*/
public void setSeqFormat(String seqFormat) {
config.seqFormat = seqFormat;
}
/**
* 设置全局的catalog,默认为空,如果设置了值,操作表时的sql会是catalog.tablename
*
* @param catalog
*/
public void setCatalog(String catalog) {
config.catalog = catalog;
}
/**
* 设置全局的schema,默认为空,如果设置了值,操作表时的sql会是schema.tablename
* <br>如果同时设置了catalog,优先使用catalog.tablename
*
* @param schema
*/
public void setSchema(String schema) {
config.schema = schema;
}
/**
* 获取表前缀,带catalog或schema
*
* @return
*/
public String getPrefix() {
if (config.catalog != null && config.catalog.length() > 0) {
return config.catalog;
}
if (config.schema != null && config.schema.length() > 0) {
return config.catalog;
}
return "";
}
/**
* 获取UUID生成规则
*
* @return
*/
public String getUUID() {
if (config.UUID != null && config.UUID.length() > 0) {
return config.UUID;
}
return "@java.util.UUID@randomUUID().toString().replace(\"-\", \"\")";
}
/**
* 获取主键自增回写SQL
*
* @return
*/
public String getIDENTITY() {
if (config.IDENTITY != null && config.IDENTITY.length() > 0) {
return config.IDENTITY;
}
//针对mysql的默认值
return IdentityDialect.MYSQL.getIdentityRetrievalStatement();
}
/**
* 获取SelectKey的Order
*
* @return
*/
public boolean getBEFORE() {
return config.BEFORE;
}
/**
* 获取序列格式化模板
*
* @return
*/
public String getSeqFormat() {
if (config.seqFormat != null && config.seqFormat.length() > 0) {
return config.seqFormat;
}
return "{0}.nextval";
}
/**
* 获取表名
*
* @param entityClass
* @return
*/
public String getTableName(Class<?> entityClass) {
EntityHelper.EntityTable entityTable = EntityHelper.getEntityTable(entityClass);
String prefix = entityTable.getPrefix();
if ("".equals(prefix)) {
//使用全局配置
prefix = getPrefix();
}
if (!"".equals(prefix)) {
return prefix + "." + entityTable.getName();
}
return entityTable.getName();
}
/**
* 判断当前的接口方法是否需要进行拦截
*
* @param msId
* @return
*/
public boolean isMapperMethod(String msId) {
if (msIdSkip.get(msId) != null) {
return msIdSkip.get(msId);
}
for (Map.Entry<Class<?>, MapperTemplate> entry : registerMapper.entrySet()) {
if (entry.getValue().supportMethod(msId)) {
msIdSkip.put(msId, true);
return true;
}
}
msIdSkip.put(msId, false);
return false;
}
/**
* 获取MapperTemplate
*
* @param msId
* @return
*/
private MapperTemplate getMapperTemplate(String msId) {
MapperTemplate mapperTemplate = null;
if (msIdCache.get(msId) != null) {
mapperTemplate = msIdCache.get(msId);
} else {
for (Map.Entry<Class<?>, MapperTemplate> entry : registerMapper.entrySet()) {
if (entry.getValue().supportMethod(msId)) {
mapperTemplate = entry.getValue();
break;
}
}
msIdCache.put(msId, mapperTemplate);
}
return mapperTemplate;
}
/**
* 重新设置SqlSource
*
* @param ms
*/
public void setSqlSource(MappedStatement ms) {
MapperTemplate mapperTemplate = getMapperTemplate(ms.getId());
try {
if (mapperTemplate != null) {
mapperTemplate.setSqlSource(ms);
}
} catch (Exception e) {
LOGGER.error("", e);
throw new BdcdjException("调用方法异常:" + e.getMessage());
}
}
/**
* 配置属性
*
* @param properties
*/
public void setProperties(Properties properties) {
if (properties == null) {
return;
}
String UUID = properties.getProperty("UUID");
if (UUID != null && UUID.length() > 0) {
setUUID(UUID);
}
String IDENTITY = properties.getProperty("IDENTITY");
if (IDENTITY != null && IDENTITY.length() > 0) {
setIDENTITY(IDENTITY);
}
String seqFormat = properties.getProperty("seqFormat");
if (seqFormat != null && seqFormat.length() > 0) {
setSeqFormat(seqFormat);
}
String catalog = properties.getProperty("catalog");
if (catalog != null && catalog.length() > 0) {
setCatalog(catalog);
}
String schema = properties.getProperty("schema");
if (schema != null && schema.length() > 0) {
setSchema(schema);
}
String ORDER = properties.getProperty("ORDER");
if (ORDER != null && ORDER.length() > 0) {
setOrder(ORDER);
}
String notEmpty = properties.getProperty("notEmpty");
if (notEmpty != null && notEmpty.length() > 0) {
this.notEmpty = "TRUE".equalsIgnoreCase(notEmpty);
}
//注册通用接口
String mapper = properties.getProperty("mappers");
if (mapper != null && mapper.length() > 0) {
String[] mappers = mapper.split(",");
for (String mapperClass : mappers) {
if (mapperClass.length() > 0) {
registerMapper(mapperClass);
}
}
}
}
/**
* 配置完成后,执行下面的操作
* <br>处理configuration中全部的MappedStatement
*
* @param configuration
*/
public void processConfiguration(Configuration configuration) {
Collection<MappedStatement> collection = configuration.getMappedStatements();
//防止反复处理一个
if (collectionSet.contains(collection)) {
return;
} else {
collectionSet.add(collection);
}
int size = collection.size();
Iterator<?> iterator = collection.iterator();
while (iterator.hasNext()) {
Object object = iterator.next();
if (object instanceof MappedStatement) {
MappedStatement ms = (MappedStatement) object;
if (isMapperMethod(ms.getId())) {
if (ms.getSqlSource() instanceof ProviderSqlSource) {
setSqlSource(ms);
}
}
}
//处理过程中可能会新增selectKey,导致ms增多,所以这里判断大小,重新循环
if (collection.size() != size) {
size = collection.size();
iterator = collection.iterator();
}
}
}
}
\ No newline at end of file
/*
* The MIT License (MIT)
*
* Copyright (c) 2014 abel533@gmail.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package cn.gtmap.bdcdj.core.mybatisMapper.mapperhelper;
import cn.gtmap.bdcdj.core.exception.BdcdjException;
import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator;
import org.apache.ibatis.executor.keygen.KeyGenerator;
import org.apache.ibatis.executor.keygen.NoKeyGenerator;
import org.apache.ibatis.executor.keygen.SelectKeyGenerator;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMap;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.ParameterMode;
import org.apache.ibatis.mapping.ResultMap;
import org.apache.ibatis.mapping.ResultMapping;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.mapping.SqlSource;
import org.apache.ibatis.mapping.StatementType;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.factory.DefaultObjectFactory;
import org.apache.ibatis.reflection.factory.ObjectFactory;
import org.apache.ibatis.reflection.wrapper.DefaultObjectWrapperFactory;
import org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory;
import org.apache.ibatis.scripting.defaults.RawSqlSource;
import org.apache.ibatis.scripting.xmltags.ChooseSqlNode;
import org.apache.ibatis.scripting.xmltags.DynamicSqlSource;
import org.apache.ibatis.scripting.xmltags.ForEachSqlNode;
import org.apache.ibatis.scripting.xmltags.IfSqlNode;
import org.apache.ibatis.scripting.xmltags.MixedSqlNode;
import org.apache.ibatis.scripting.xmltags.SqlNode;
import org.apache.ibatis.scripting.xmltags.StaticTextSqlNode;
import org.apache.ibatis.scripting.xmltags.TextSqlNode;
import org.apache.ibatis.scripting.xmltags.TrimSqlNode;
import org.apache.ibatis.scripting.xmltags.WhereSqlNode;
import org.apache.ibatis.session.Configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* 通用Mapper模板类,扩展通用Mapper时需要继承该类
*
* @author liuzh
*/
public abstract class MapperTemplate {
private static final Logger LOGGER = LoggerFactory.getLogger(MapperTemplate.class);
private Map<String, Method> methodMap = new HashMap<String, Method>();
private Class<?> mapperClass;
private MapperHelper mapperHelper;
public MapperTemplate(Class<?> mapperClass, MapperHelper mapperHelper) {
this.mapperClass = mapperClass;
this.mapperHelper = mapperHelper;
}
public String dynamicSQL(Object record) {
return "dynamicSQL";
}
/**
* 添加映射方法
*
* @param methodName
* @param method
*/
public void addMethodMap(String methodName, Method method) {
methodMap.put(methodName, method);
}
public String getUUID() {
return mapperHelper.getUUID();
}
public String getIDENTITY() {
return mapperHelper.getIDENTITY();
}
public boolean getBEFORE() {
return mapperHelper.getBEFORE();
}
private static final ObjectFactory DEFAULT_OBJECT_FACTORY = new DefaultObjectFactory();
private static final ObjectWrapperFactory DEFAULT_OBJECT_WRAPPER_FACTORY = new DefaultObjectWrapperFactory();
/**
* 反射对象,增加对低版本Mybatis的支持
*
* @param object 反射对象
* @return
*/
public static MetaObject forObject(Object object) {
return MetaObject.forObject(object, DEFAULT_OBJECT_FACTORY, DEFAULT_OBJECT_WRAPPER_FACTORY);
}
/**
* 是否支持该通用方法
*
* @param msId
* @return
*/
public boolean supportMethod(String msId) {
Class<?> mapperClass = getMapperClass(msId);
if (mapperClass != null && this.mapperClass.isAssignableFrom(mapperClass)) {
String methodName = getMethodName(msId);
return methodMap.get(methodName) != null;
}
return false;
}
/**
* 设置返回值类型
*
* @param ms
* @param entityClass
*/
protected void setResultType(MappedStatement ms, Class<?> entityClass) {
ResultMap resultMap = ms.getResultMaps().get(0);
MetaObject metaObject = forObject(resultMap);
metaObject.setValue("type", entityClass);
}
/**
* 重新设置SqlSource
*
* @param ms
* @param sqlSource
*/
protected void setSqlSource(MappedStatement ms, SqlSource sqlSource) {
MetaObject msObject = forObject(ms);
msObject.setValue("sqlSource", sqlSource);
}
/**
* 重新设置SqlSource
*
* @param ms
* @throws InvocationTargetException
* @throws IllegalAccessException
*/
public void setSqlSource(MappedStatement ms){
if (this.mapperClass == getMapperClass(ms.getId())) {
if (mapperHelper.isSpring4()) {
return;
} else if (mapperHelper.isSpring()) {
throw new BdcdjException("Spring4.x.x 及以上版本支持泛型注入," +
"您当前的Spring版本为" + mapperHelper.getSpringVersion() + ",不能使用泛型注入," +
"因此在配置MapperScannerConfigurer时,不要扫描通用Mapper接口类," +
"也不要在您Mybatis的xml配置文件中的<mappers>中指定通用Mapper接口类.");
} else {
throw new BdcdjException("请不要在您Mybatis的xml配置文件中的<mappers>中指定通用Mapper接口类.");
}
}
Method method = methodMap.get(getMethodName(ms));
try {
if (method.getReturnType() == Void.TYPE) {
method.invoke(this, ms);
} else if (SqlNode.class.isAssignableFrom(method.getReturnType())) {
SqlNode sqlNode = (SqlNode) method.invoke(this, ms);
DynamicSqlSource dynamicSqlSource = new DynamicSqlSource(ms.getConfiguration(), sqlNode);
setSqlSource(ms, dynamicSqlSource);
} else {
throw new BdcdjException("自定义Mapper方法返回类型错误,可选的返回类型为void和SqlNode!");
}
} catch (IllegalAccessException e) {
LOGGER.debug("", e);
throw new BdcdjException(e);
} catch (InvocationTargetException e) {
throw new BdcdjException(e.getTargetException() != null ? e.getTargetException() : e);
}
}
/**
* 获取返回值类型 - 实体类型
*
* @param ms
* @return
*/
public Class<?> getSelectReturnType(MappedStatement ms) {
String msId = ms.getId();
Class<?> mapperClass = getMapperClass(msId);
Type[] types = mapperClass.getGenericInterfaces();
for (Type type : types) {
if (type instanceof ParameterizedType) {
ParameterizedType t = (ParameterizedType) type;
if (t.getRawType() == this.mapperClass) {
Class<?> returnType = (Class<?>) t.getActualTypeArguments()[0];
return returnType;
}
}
}
throw new BdcdjException("无法获取Mapper<T>泛型类型:" + msId);
}
/**
* 根据msId获取接口类
*
* @param msId
* @return
* @throws ClassNotFoundException
*/
public static Class<?> getMapperClass(String msId) {
if (msId.indexOf(".") == -1) {
throw new BdcdjException("当前MappedStatement的id=" + msId + ",不符合MappedStatement的规则!");
}
String mapperClassStr = msId.substring(0, msId.lastIndexOf("."));
try {
return Class.forName(mapperClassStr);
} catch (ClassNotFoundException e) {
LOGGER.debug("", e);
return null;
}
}
/**
* 获取执行的方法名
*
* @param ms
* @return
*/
public static String getMethodName(MappedStatement ms) {
return getMethodName(ms.getId());
}
/**
* 获取执行的方法名
*
* @param msId
* @return
*/
public static String getMethodName(String msId) {
return msId.substring(msId.lastIndexOf(".") + 1);
}
/**
* 根据对象生成主键映射
*
* @param ms
* @return
*/
protected List<ParameterMapping> getPrimaryKeyParameterMappings(MappedStatement ms) {
Class<?> entityClass = getSelectReturnType(ms);
Set<EntityHelper.EntityColumn> entityColumns = EntityHelper.getPKColumns(entityClass);
List<ParameterMapping> parameterMappings = new ArrayList<ParameterMapping>();
for (EntityHelper.EntityColumn column : entityColumns) {
ParameterMapping.Builder builder = new ParameterMapping.Builder(ms.getConfiguration(), column.getProperty(), column.getJavaType());
builder.mode(ParameterMode.IN);
parameterMappings.add(builder.build());
}
return parameterMappings;
}
/**
* 获取序列下个值的表达式
*
* @param column
* @return
*/
protected String getSeqNextVal(EntityHelper.EntityColumn column) {
return MessageFormat.format(mapperHelper.getSeqFormat(), column.getSequenceName(), column.getColumn(), column.getProperty());
}
/**
* 获取实体类的表名
*
* @param entityClass
* @return
*/
protected String tableName(Class<?> entityClass) {
return mapperHelper.getTableName(entityClass);
}
/**
* 返回if条件的sqlNode
* <p>一般类型:<code>&lt;if test="property!=null"&gt;columnNode&lt;/if&gt;</code></p>
*
* @param column
* @param columnNode
* @return
*/
protected SqlNode getIfNotNull(EntityHelper.EntityColumn column, SqlNode columnNode) {
return getIfNotNull(column, columnNode, false);
}
/**
* 返回if条件的sqlNode
* <p>一般类型:<code>&lt;if test="property!=null"&gt;columnNode&lt;/if&gt;</code></p>
*
* @param column
* @param columnNode
* @param empty 是否包含!=''条件
* @return
*/
protected SqlNode getIfNotNull(EntityHelper.EntityColumn column, SqlNode columnNode, boolean empty) {
return new IfSqlNode(columnNode, column.getProperty() + " != null " + (empty ? " and " + column.getProperty() + " != ''" : ""));
}
/**
* 返回if条件的sqlNode
* <p>一般类型:<code>&lt;if test="property==null"&gt;columnNode&lt;/if&gt;</code></p>
*
* @param column
* @return
*/
protected SqlNode getIfIsNull(EntityHelper.EntityColumn column, SqlNode columnNode) {
return new IfSqlNode(columnNode, column.getProperty() + " == null ");
}
/**
* 返回if条件的sqlNode
* <p>一般类型:<code>&lt;if test="property!=null"&gt;columnNode&lt;/if&gt;</code></p>
*
* @param column
* @return
*/
protected SqlNode getIfCacheNotNull(EntityHelper.EntityColumn column, SqlNode columnNode) {
return new IfSqlNode(columnNode, column.getProperty() + "_cache != null ");
}
/**
* 返回if条件的sqlNode
* <p>一般类型:<code>&lt;if test="property_cache!=null"&gt;columnNode&lt;/if&gt;</code></p>
*
* @param column
* @return
*/
protected SqlNode getIfCacheIsNull(EntityHelper.EntityColumn column, SqlNode columnNode) {
return new IfSqlNode(columnNode, column.getProperty() + "_cache == null ");
}
/**
* 获取 <code>[AND] column = #{property}</code>
*
* @param column
* @param first
* @return
*/
protected SqlNode getColumnEqualsProperty(EntityHelper.EntityColumn column, boolean first) {
return new StaticTextSqlNode((first ? "" : " AND ") + column.getColumn() + " = #{" + column.getProperty() + "} ");
}
/**
* 获取所有列的where节点中的if判断列
*
* @param entityClass
* @return
*/
protected SqlNode getAllIfColumnNode(Class<?> entityClass) {
//获取全部列
Set<EntityHelper.EntityColumn> columnList = EntityHelper.getColumns(entityClass);
List<SqlNode> ifNodes = new ArrayList<SqlNode>();
boolean first = true;
//对所有列循环,生成<if test="property!=null">column = #{property}</if>
for (EntityHelper.EntityColumn column : columnList) {
ifNodes.add(getIfNotNull(column, getColumnEqualsProperty(column, first), mapperHelper.isNotEmpty()));
first = false;
}
return new MixedSqlNode(ifNodes);
}
/**
* 根据对象生成所有列的映射
*
* @param ms
* @return
*/
protected List<ParameterMapping> getColumnParameterMappings(MappedStatement ms) {
Class<?> entityClass = getSelectReturnType(ms);
Set<EntityHelper.EntityColumn> entityColumns = EntityHelper.getColumns(entityClass);
List<ParameterMapping> parameterMappings = new ArrayList<ParameterMapping>();
for (EntityHelper.EntityColumn column : entityColumns) {
ParameterMapping.Builder builder = new ParameterMapping.Builder(ms.getConfiguration(), column.getProperty(), column.getJavaType());
builder.mode(ParameterMode.IN);
parameterMappings.add(builder.build());
}
return parameterMappings;
}
/**
* 新建SelectKey节点 - 只对mysql的自动增长有效,Oracle序列直接写到列中
*
* @param ms
* @param column
*/
protected void newSelectKeyMappedStatement(MappedStatement ms, EntityHelper.EntityColumn column) {
String keyId = ms.getId() + SelectKeyGenerator.SELECT_KEY_SUFFIX;
if (ms.getConfiguration().hasKeyGenerator(keyId)) {
return;
}
Class<?> entityClass = getSelectReturnType(ms);
//defaults
Configuration configuration = ms.getConfiguration();
KeyGenerator keyGenerator = null;
Boolean executeBefore = getBEFORE();
String IDENTITY = (column.getGenerator() == null || "".equals(column.getGenerator())) ? getIDENTITY() : column.getGenerator();
if ("JDBC".equalsIgnoreCase(IDENTITY)) {
keyGenerator = new Jdbc3KeyGenerator();
} else {
SqlSource sqlSource = new RawSqlSource(configuration, IDENTITY, entityClass);
MappedStatement.Builder statementBuilder = new MappedStatement.Builder(configuration, keyId, sqlSource, SqlCommandType.SELECT);
statementBuilder.resource(ms.getResource());
statementBuilder.fetchSize(null);
statementBuilder.statementType(StatementType.STATEMENT);
statementBuilder.keyGenerator(new NoKeyGenerator());
statementBuilder.keyProperty(column.getProperty());
statementBuilder.keyColumn(null);
statementBuilder.databaseId(null);
statementBuilder.lang(configuration.getDefaultScriptingLanuageInstance());
statementBuilder.resultOrdered(false);
statementBuilder.resulSets(null);
statementBuilder.timeout(configuration.getDefaultStatementTimeout());
List<ParameterMapping> parameterMappings = new ArrayList<ParameterMapping>();
ParameterMap.Builder inlineParameterMapBuilder = new ParameterMap.Builder(
configuration,
statementBuilder.id() + "-Inline",
entityClass,
parameterMappings);
statementBuilder.parameterMap(inlineParameterMapBuilder.build());
List<ResultMap> resultMaps = new ArrayList<ResultMap>();
ResultMap.Builder inlineResultMapBuilder = new ResultMap.Builder(
configuration,
statementBuilder.id() + "-Inline",
column.getJavaType(),
new ArrayList<ResultMapping>(),
null);
resultMaps.add(inlineResultMapBuilder.build());
statementBuilder.resultMaps(resultMaps);
statementBuilder.resultSetType(null);
statementBuilder.flushCacheRequired(false);
statementBuilder.useCache(false);
statementBuilder.cache(null);
MappedStatement statement = statementBuilder.build();
configuration.addMappedStatement(statement);
MappedStatement keyStatement = configuration.getMappedStatement(keyId, false);
keyGenerator = new SelectKeyGenerator(keyStatement, executeBefore);
configuration.addKeyGenerator(keyId, keyGenerator);
}
//keyGenerator
try {
MetaObject msObject = forObject(ms);
msObject.setValue("keyGenerator", keyGenerator);
msObject.setValue("keyProperties", new String[]{column.getProperty()});
} catch (Exception e) {
LOGGER.debug("", e);
//ignore
}
}
public IfSqlNode ExampleValidSqlNode(Configuration configuration) {
List<SqlNode> whenSqlNodes = new ArrayList<SqlNode>();
IfSqlNode noValueSqlNode = new IfSqlNode(new TextSqlNode("and ${criterion.condition}"), "criterion.noValue");
whenSqlNodes.add(noValueSqlNode);
IfSqlNode singleValueSqlNode = new IfSqlNode(new TextSqlNode("and ${criterion.condition} #{criterion.value}"), "criterion.singleValue");
whenSqlNodes.add(singleValueSqlNode);
IfSqlNode betweenValueSqlNode = new IfSqlNode(new TextSqlNode("and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}"), "criterion.betweenValue");
whenSqlNodes.add(betweenValueSqlNode);
List<SqlNode> listValueContentSqlNodes = new ArrayList<SqlNode>();
listValueContentSqlNodes.add(new TextSqlNode("and ${criterion.condition}"));
ForEachSqlNode listValueForEachSqlNode = new ForEachSqlNode(configuration, new StaticTextSqlNode("#{listItem}"), "criterion.value", null, "listItem", "(", ")", ",");
listValueContentSqlNodes.add(listValueForEachSqlNode);
IfSqlNode listValueSqlNode = new IfSqlNode(new MixedSqlNode(listValueContentSqlNodes), "criterion.noValue");
whenSqlNodes.add(listValueSqlNode);
ChooseSqlNode chooseSqlNode = new ChooseSqlNode(whenSqlNodes, null);
ForEachSqlNode criteriaSqlNode = new ForEachSqlNode(configuration, chooseSqlNode, "criteria.criteria", null, "criterion", null, null, null);
TrimSqlNode trimSqlNode = new TrimSqlNode(configuration, criteriaSqlNode, "(", "and", ")", null);
IfSqlNode validSqlNode = new IfSqlNode(trimSqlNode, "criteria.valid");
return validSqlNode;
}
/**
* Example查询中的where结构
*
* @param configuration
* @return
*/
public WhereSqlNode exampleWhereClause(Configuration configuration) {
ForEachSqlNode forEachSqlNode = new ForEachSqlNode(configuration, ExampleValidSqlNode(configuration), "oredCriteria", null, "criteria", null, null, "or");
WhereSqlNode whereSqlNode = new WhereSqlNode(configuration, forEachSqlNode);
return whereSqlNode;
}
/**
* Example-Update中的where结构
*
* @param configuration
* @return
*/
public WhereSqlNode updateByExampleWhereClause(Configuration configuration) {
//和上面方法的区别就在"example.oredCriteria"
ForEachSqlNode forEachSqlNode = new ForEachSqlNode(configuration, ExampleValidSqlNode(configuration), "example.oredCriteria", null, "criteria", null, null, "or");
WhereSqlNode whereSqlNode = new WhereSqlNode(configuration, forEachSqlNode);
return whereSqlNode;
}
}
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论