All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.chengyuxing.sql.EntityManager Maven / Gradle / Ivy

Go to download

Light wrapper of JDBC, support ddl, dml, query, plsql/procedure/function, transaction and manage sql file.

There is a newer version: 9.0.2
Show newest version
package com.github.chengyuxing.sql;

import com.github.chengyuxing.common.utils.ReflectUtil;
import com.github.chengyuxing.sql.dsl.types.StandardOperator;
import org.jetbrains.annotations.NotNull;

import javax.persistence.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Entity manager.
 *
 * @see Entity @Entity
 * @see Table @Table
 * @see Id @Id
 * @see Column @Column
 * @see Transient @Transient
 */
public class EntityManager implements AutoCloseable {
    private final Map, EntityMeta> classInformation = new ConcurrentHashMap<>();
    private final char namedParamPrefix;

    public EntityManager(char namedParamPrefix) {
        if (namedParamPrefix == ' ') {
            throw new IllegalArgumentException("prefix char cannot be empty.");
        }
        this.namedParamPrefix = namedParamPrefix;
    }

    public  EntityMeta getEntityMeta(@NotNull Class clazz) {
        if (!clazz.isAnnotationPresent(Entity.class)) {
            throw new IllegalStateException(clazz.getName() + " must be annotated with @" + Entity.class.getSimpleName());
        }
        return classInformation.computeIfAbsent(clazz, c -> new EntityMeta(namedParamPrefix, checkTableName(c), checkColumns(c)));
    }

    public String getTableName(@NotNull Class clazz) {
        return getEntityMeta(clazz).getTableName();
    }

    public Map getColumns(@NotNull Class clazz) {
        return getEntityMeta(clazz).getColumns();
    }

    public char getNamedParamPrefix() {
        return namedParamPrefix;
    }

    private String checkTableName(Class clazz) {
        String tableName = clazz.getSimpleName().toLowerCase();
        if (clazz.isAnnotationPresent(Table.class)) {
            Table table = clazz.getAnnotation(Table.class);
            if (!table.name().isEmpty()) {
                tableName = table.name();
            }
            if (!table.schema().isEmpty()) {
                tableName = table.schema() + "." + tableName;
            }
        }
        return tableName;
    }

    private Map checkColumns(Class clazz) {
        Map columns = new HashMap<>();
        try {
            for (Field field : clazz.getDeclaredFields()) {
                int modifiers = field.getModifiers();
                if (Modifier.isFinal(modifiers) || Modifier.isStatic(modifiers)) {
                    continue;
                }
                if (field.isAnnotationPresent(Transient.class)) {
                    continue;
                }
                Method getter = ReflectUtil.getGetMethod(clazz, field);
                Method setter = ReflectUtil.getSetMethod(clazz, field);
                ColumnMeta columnMeta = new ColumnMeta(getter, setter, field.getType(), field.getAnnotation(Id.class));
                String columnName = field.getName();
                if (field.isAnnotationPresent(Column.class)) {
                    columnMeta.setColumn(field.getAnnotation(Column.class));
                    String name = field.getAnnotation(Column.class).name().trim();
                    if (!name.isEmpty()) {
                        columnName = name;
                    }
                }
                columns.put(columnName, columnMeta);
            }
            return columns;
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void close() throws Exception {
        classInformation.clear();
    }

    public static final class EntityMeta {
        private final char namedParamPrefix;
        private final String tableName;
        private final String primaryKey;
        private final String whereById;
        private final Map columns;
        private final Set updateColumns;
        private final Set insertColumns;
        private final String select;
        private final String countSelect;
        private final String existsSelect;
        private final String insert;
        private final String updateById;
        private final String deleteById;

        public EntityMeta(char namedParamPrefix, String tableName, Map columns) {
            this.namedParamPrefix = namedParamPrefix;
            this.tableName = tableName;
            this.columns = columns;
            this.primaryKey = checkPrimaryKey();
            this.whereById = genWhereById();
            this.updateColumns = genUpdateSetColumns();
            this.insertColumns = genInsertColumns();
            this.select = genSelect(this.columns.keySet());
            this.countSelect = genCountSelect();
            this.existsSelect = genExistSelect();
            this.insert = genInsert();
            this.updateById = genUpdate();
            this.deleteById = genDelete();
        }

        public String getPrimaryKey() {
            return primaryKey;
        }

        public String getWhereById() {
            return whereById;
        }

        public Map getColumns() {
            return columns;
        }

        public Set getInsertColumns() {
            return insertColumns;
        }

        public Set getUpdateColumns() {
            return updateColumns;
        }

        public String getTableName() {
            return tableName;
        }

        public String getSelect() {
            return select;
        }

        public String getSelect(Set columns) {
            return genSelect(columns);
        }

        public String getCountSelect() {
            return countSelect;
        }

        public String getExistsSelect() {
            return existsSelect;
        }

        public String getInsert() {
            return insert;
        }

        public String getUpdateById() {
            return updateById;
        }

        public String getDeleteById() {
            return deleteById;
        }

        private String checkPrimaryKey() {
            for (Map.Entry entry : columns.entrySet()) {
                if (Objects.nonNull(entry.getValue().getId())) {
                    return entry.getKey();
                }
            }
            throw new IllegalStateException("Primary Key not found");
        }

        private String genWhereById() {
            return "\nwhere " + primaryKey + StandardOperator.EQ.padWithSpace() + namedParamPrefix + primaryKey;
        }

        private String genSelect(Set columns) {
            String delimiter = columns.size() > 7 ? ",\n\t" : ", ";
            return "select " + String.join(delimiter, columns) + "\nfrom " + tableName;
        }

        private String genCountSelect() {
            return "select count(*)\nfrom " + tableName;
        }

        private String genExistSelect() {
            return "select 1 from " + tableName;
        }

        private Set genInsertColumns() {
            Set insertColumns = new HashSet<>();
            for (Map.Entry entry : columns.entrySet()) {
                Column column = entry.getValue().getColumn();
                if (Objects.isNull(column) || column.insertable()) {
                    insertColumns.add(entry.getKey());
                }
            }
            return insertColumns;
        }

        private String genInsert() {
            StringJoiner f = new StringJoiner(", ");
            StringJoiner h = new StringJoiner(", ");
            for (String column : insertColumns) {
                f.add(column);
                h.add(namedParamPrefix + column);
            }
            return "insert into " + tableName + "(" + f + ") values (" + h + ")";
        }

        private Set genUpdateSetColumns() {
            Set setColumns = new HashSet<>();
            for (Map.Entry entry : columns.entrySet()) {
                if (Objects.nonNull(entry.getValue().getId())) {
                    continue;
                }
                Column column = entry.getValue().getColumn();
                if (Objects.isNull(column) || column.updatable()) {
                    setColumns.add(entry.getKey());
                }
            }
            return setColumns;
        }

        private String genUpdate() {
            StringJoiner sets = new StringJoiner(",\n\t");
            for (String column : updateColumns) {
                sets.add(column + StandardOperator.EQ.padWithSpace() + namedParamPrefix + column);
            }
            return "update " + tableName + "\nset " + sets + whereById;
        }

        private String genDelete() {
            return "delete from " + tableName + whereById;
        }
    }

    public static final class ColumnMeta {
        private final Method getter;
        private final Method setter;
        private final Class type;
        private final Id id;
        private Column column;

        public ColumnMeta(Method getter, Method setter, Class type, Id id) {
            this.getter = getter;
            this.setter = setter;
            this.type = type;
            this.id = id;
        }

        public Method getGetter() {
            return getter;
        }

        public Class getType() {
            return type;
        }

        public Method getSetter() {
            return setter;
        }

        public Id getId() {
            return id;
        }

        public Column getColumn() {
            return column;
        }

        public void setColumn(Column column) {
            this.column = column;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy