com.github.abel533.mapperhelper.EntityHelper Maven / Gradle / Ivy
The newest version!
/*
* The MIT License (MIT)
*
* Copyright (c) 2014 [email protected]
*
* 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 com.github.abel533.mapperhelper;
import org.apache.commons.beanutils.BeanUtils;
import javax.persistence.*;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 实体类工具类 - 处理实体和数据库表以及字段关键的一个类
*
* 项目地址 : https://github.com/abel533/Mapper
*
* @author liuzh
*/
public class EntityHelper {
/**
* 实体对应表的配置信息
*/
public static class EntityTable {
private String name;
private String catalog;
private String schema;
private String orderByClause;
//实体类 => 全部列属性
private Set entityClassColumns;
//实体类 => 主键信息
private Set entityClassPKColumns;
//字段名和属性名的映射
private Map aliasMap;
//useGenerator包含多列的时候需要用到
private List keyProperties;
private List keyColumns;
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 getEntityClassColumns() {
return entityClassColumns;
}
public Set getEntityClassPKColumns() {
return entityClassPKColumns;
}
public Map getAliasMap() {
return aliasMap;
}
public String[] getKeyProperties() {
if (keyProperties != null && keyProperties.size() > 0) {
return keyProperties.toArray(new String[]{});
}
return new String[]{};
}
public void setKeyProperties(String keyProperty) {
if (this.keyProperties == null) {
this.keyProperties = new LinkedList();
this.keyProperties.add(keyProperty);
} else {
this.keyProperties.add(keyProperty);
}
}
public String[] getKeyColumns() {
if (keyColumns != null && keyColumns.size() > 0) {
return keyColumns.toArray(new String[]{});
}
return new String[]{};
}
public void setKeyColumns(String keyColumn) {
if (this.keyColumns == null) {
this.keyColumns = new LinkedList();
this.keyColumns.add(keyColumn);
} else {
this.keyColumns.add(keyColumn);
}
}
}
/**
* 实体字段对应数据库列的信息
*/
public static class EntityColumn {
private EntityTable table;
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 EntityColumn() {
}
public EntityColumn(EntityTable table) {
this.table = table;
}
public EntityTable getTable() {
return table;
}
public void setTable(EntityTable table) {
this.table = table;
}
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, EntityTable> entityTableMap = new HashMap, 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 RuntimeException("无法获取实体类" + entityClass.getCanonicalName() + "对应的表名!");
}
return entityTable;
}
/**
* 获取默认的orderby语句
*
* @param entityClass
* @return
*/
public static String getOrderByClause(Class> entityClass) {
EntityTable table = getEntityTable(entityClass);
if (table.orderByClause != null) {
return table.orderByClause;
}
StringBuilder orderBy = new StringBuilder();
for (EntityHelper.EntityColumn column : table.getEntityClassColumns()) {
if (column.getOrderBy() != null) {
if (orderBy.length() != 0) {
orderBy.append(",");
}
orderBy.append(column.getColumn()).append(" ").append(column.getOrderBy());
}
}
table.orderByClause = orderBy.toString();
return table.orderByClause;
}
/**
* 获取全部列
*
* @param entityClass
* @return
*/
public static Set getColumns(Class> entityClass) {
return getEntityTable(entityClass).getEntityClassColumns();
}
/**
* 获取主键信息
*
* @param entityClass
* @return
*/
public static Set getPKColumns(Class> entityClass) {
return getEntityTable(entityClass).getEntityClassPKColumns();
}
/**
* 获取字段映射关系
*
* @param entityClass
* @return
*/
public static Map getColumnAlias(Class> entityClass) {
EntityTable entityTable = getEntityTable(entityClass);
if (entityTable.aliasMap != null) {
return entityTable.aliasMap;
}
Set columnList = entityTable.getEntityClassColumns();
entityTable.aliasMap = new HashMap(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 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 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 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 (!table.name().equals("")) {
entityTable = new EntityTable();
entityTable.setTable(table);
}
}
if (entityTable == null) {
entityTable = new EntityTable();
//对大小写敏感的情况,这里不自动转换大小写,如果有需要,通过@Table注解实现
entityTable.name = camelhumpToUnderline(entityClass.getSimpleName());
}
//列
List fieldList = getAllField(entityClass, null);
Set columnSet = new LinkedHashSet();
Set pkColumnSet = new LinkedHashSet();
for (Field field : fieldList) {
//排除字段
if (field.isAnnotationPresent(Transient.class)) {
continue;
}
EntityColumn entityColumn = new EntityColumn(entityTable);
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 || columnName.equals("")) {
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 (orderBy.value().equals("")) {
entityColumn.setOrderBy("ASC");
} else {
entityColumn.setOrderBy(orderBy.value());
}
}
//主键策略 - Oracle序列,MySql自动增长,UUID
if (field.isAnnotationPresent(SequenceGenerator.class)) {
SequenceGenerator sequenceGenerator = field.getAnnotation(SequenceGenerator.class);
if (sequenceGenerator.sequenceName().equals("")) {
throw new RuntimeException(entityClass + "字段" + field.getName() + "的注解@SequenceGenerator未指定sequenceName!");
}
entityColumn.setSequenceName(sequenceGenerator.sequenceName());
} else if (field.isAnnotationPresent(GeneratedValue.class)) {
GeneratedValue generatedValue = field.getAnnotation(GeneratedValue.class);
if (generatedValue.generator().equals("UUID")) {
entityColumn.setUuid(true);
} else if (generatedValue.generator().equals("JDBC")) {
entityColumn.setIdentity(true);
entityColumn.setGenerator("JDBC");
entityTable.setKeyProperties(entityColumn.getProperty());
entityTable.setKeyColumns(entityColumn.getColumn());
} else {
//允许通过generator来设置获取id的sql,例如mysql=CALL IDENTITY(),hsqldb=SELECT SCOPE_IDENTITY()
//允许通过拦截器参数设置公共的generator
if (generatedValue.strategy() == GenerationType.IDENTITY) {
//mysql的自动增长
entityColumn.setIdentity(true);
if (!generatedValue.generator().equals("")) {
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 RuntimeException(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 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 String underlineToCamelhump(String str) {
Matcher matcher = Pattern.compile("_[a-z]").matcher(str);
StringBuilder builder = new StringBuilder(str);
for (int i = 0; matcher.find(); i++) {
builder.replace(matcher.start() - i, matcher.end() - i, matcher.group().substring(1).toUpperCase());
}
if (Character.isUpperCase(builder.charAt(0))) {
builder.replace(0, 1, String.valueOf(Character.toLowerCase(builder.charAt(0))));
}
return builder.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 getAllField(Class> entityClass, List fieldList) {
if (fieldList == null) {
fieldList = new LinkedList();
}
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 map2AliasMap(Map map, Class> beanClass) {
if (map == null) {
return null;
}
Map alias = getColumnAlias(beanClass);
Map result = new HashMap();
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 map, Class> beanClass) {
try {
if (map == null) {
return null;
}
Map aliasMap = map2AliasMap(map, beanClass);
Object bean = beanClass.newInstance();
BeanUtils.copyProperties(bean, aliasMap);
return bean;
} catch (InstantiationException e) {
throw new RuntimeException(beanClass.getCanonicalName() + "类没有默认空的构造方法!");
} catch (Exception e) {
throw new RuntimeException(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 LinkedList