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

ars.database.hibernate.Hibernates Maven / Gradle / Ivy

The newest version!
package ars.database.hibernate;

import java.util.Map;
import java.util.Set;
import java.util.List;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.ArrayList;
import java.util.Map.Entry;
import java.util.Collection;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.net.URLDecoder;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

import org.hibernate.Session;
import org.hibernate.Hibernate;
import org.hibernate.SessionFactory;
import org.hibernate.type.Type;
import org.hibernate.type.CollectionType;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.engine.spi.SessionFactoryImplementor;

import ars.util.Beans;
import ars.util.Strings;
import ars.database.model.Model;
import ars.database.model.TreeModel;
import ars.database.repository.Query;

/**
 * Hibernate操作工具类
 *
 * @author wuyongqiang
 */
public final class Hibernates {
    private Hibernates() {

    }

    /**
     * 获取数据模型元对象
     *
     * @param sessionFactory 会话工厂
     * @param model          数据模型
     * @return 元对象
     */
    public static ClassMetadata getClassMetadata(SessionFactory sessionFactory, Class model) {
        ClassMetadata metadata = sessionFactory.getClassMetadata(model);
        if (metadata == null) {
            throw new IllegalStateException("Class metadata not found:" + model.getName());
        }
        return metadata;
    }

    /**
     * 获取模型主键名称
     *
     * @param sessionFactory 会话工厂
     * @param model          模型对象
     * @return 主键名称
     */
    public static String getPrimary(SessionFactory sessionFactory, Class model) {
        return getClassMetadata(sessionFactory, model).getIdentifierPropertyName();
    }

    /**
     * 获取主键类型
     *
     * @param sessionFactory 会话工厂
     * @param model          模型对象
     * @return 主键类型
     */
    public static Class getPrimaryClass(SessionFactory sessionFactory, Class model) {
        return getClassMetadata(sessionFactory, model).getIdentifierType().getReturnedClass();
    }

    /**
     * 获取对象主键值
     *
     * @param sessionFactory 会话工厂
     * @param object         对象实例
     * @return 主键值
     */
    public static Serializable getIdentifier(SessionFactory sessionFactory, Object object) {
        return object == null ? null : object instanceof Model ? ((Model) object).getId() : (Serializable) Beans
            .getValue(object, getPrimary(sessionFactory, object.getClass()));
    }

    /**
     * 设置对象主键值
     *
     * @param sessionFactory 会话工厂
     * @param object         对象实例
     * @param id             主键值
     */
    public static void setIdentifier(SessionFactory sessionFactory, Object object, Object id) {
        if (object != null && id != null) {
            if (object instanceof Model) {
                ((Model) object).setId(Beans.toInteger(int.class, id));
            } else {
                Beans.setValue(object, getPrimary(sessionFactory, object.getClass()), id);
            }
        }
    }

    /**
     * 获取模型属性
     *
     * @param sessionFactory 会话工厂
     * @param model          数据模型
     * @return 属性名称数组
     */
    public static String[] getProperties(SessionFactory sessionFactory, Class model) {
        return getClassMetadata(sessionFactory, model).getPropertyNames();
    }

    /**
     * 获取类型对象
     *
     * @param sessionFactory 会话工厂
     * @param type           属性映射类型对象
     * @return 类型对象
     */
    public static Class getPropertyTypeClass(SessionFactory sessionFactory, Type type) {
        return type.isCollectionType() ? ((CollectionType) type).getElementType(
            (SessionFactoryImplementor) sessionFactory).getReturnedClass() : type.getReturnedClass();
    }

    /**
     * 获取模型属性类型
     *
     * @param sessionFactory 会话工厂
     * @param model          数据模型
     * @param property       属性名称
     * @return 类型对象
     */
    public static Type getPropertyType(SessionFactory sessionFactory, Class model, String property) {
        int index = property.indexOf('.');
        if (index > 0) {
            Type type = getPropertyType(sessionFactory, model, property.substring(0, index));
            return getPropertyType(sessionFactory, getPropertyTypeClass(sessionFactory, type),
                property.substring(index + 1));
        }
        ClassMetadata metadata = getClassMetadata(sessionFactory, model);
        if (metadata.hasIdentifierProperty() && metadata.getIdentifierPropertyName().equals(property)) {
            return metadata.getIdentifierType();
        }
        return metadata.getPropertyType(property);
    }

    /**
     * 获取模型属性类型
     *
     * @param sessionFactory 会话工厂
     * @param model          数据模型
     * @param property       属性名称
     * @return 属性类型
     */
    public static Class getPropertyClass(SessionFactory sessionFactory, Class model, String property) {
        Type type = getPropertyType(sessionFactory, model, property);
        return getPropertyTypeClass(sessionFactory, type);
    }

    /**
     * 获取对象属性值
     *
     * @param sessionFactory 会话工厂
     * @param object         对象实例
     * @param property       属性名称
     * @return 属性值
     */
    public static Object getValue(SessionFactory sessionFactory, Object object, String property) {
        if (object == null) {
            return null;
        }
        ClassMetadata metadata = getClassMetadata(sessionFactory, object.getClass());
        Object value = metadata.getPropertyValue(object, property);
        if (value != null && !Hibernate.isInitialized(value)) {
            Type type = metadata.getPropertyType(property);
            return type.isCollectionType() ? new ArrayList(0) : null;
        }
        return value;
    }

    /**
     * 获取对象多个属性值
     *
     * @param sessionFactory 会话工厂
     * @param object         对象实例
     * @param properties     属性名称数组
     * @return 属性名称/值键值对
     */
    public static Map getValues(SessionFactory sessionFactory, Object object, String... properties) {
        if (object == null) {
            return new HashMap(0);
        }
        if (properties == null || properties.length == 0) {
            properties = getProperties(sessionFactory, object.getClass());
        }
        Map values = new HashMap(properties.length);
        for (String property : properties) {
            values.put(property, getValue(sessionFactory, object, property));
        }
        return values;
    }

    /**
     * 设置对象属性值
     *
     * @param sessionFactory 会话工厂
     * @param object         对象实例
     * @param property       属性名称
     * @param value          属性值
     */
    public static void setValue(SessionFactory sessionFactory, Object object, String property, Object value) {
        if (object == null) {
            return;
        }
        ClassMetadata metadata = getClassMetadata(sessionFactory, object.getClass());
        Type type = metadata.getPropertyType(property);
        Class meta = getPropertyTypeClass(sessionFactory, type);
        if (type.isEntityType()) { // 多对一
            if (value != null && !meta.isAssignableFrom(value.getClass())) {
                Serializable id = (Serializable) Beans.toObject(getPrimaryClass(sessionFactory, meta), value);
                Session session = sessionFactory.openSession();
                try {
                    value = session.get(meta, id);
                } finally {
                    session.close();
                }
            }
            metadata.setPropertyValue(object, property, value);
        } else if (type.isCollectionType()) { // 多对多
            Object[] values = Beans.toArray(Object.class, value);
            Collection objects = Set.class.isAssignableFrom(type.getReturnedClass()) ? new HashSet(
                values.length) : new ArrayList(values.length);
            if (values.length > 0) {
                Session session = null;
                Class foreignPrimaryClass = getPrimaryClass(sessionFactory, meta);
                try {
                    for (Object v : values) {
                        if (v != null && !meta.isAssignableFrom(v.getClass())) {
                            if (session == null) {
                                session = sessionFactory.openSession();
                            }
                            Serializable id = (Serializable) Beans.toObject(foreignPrimaryClass, v);
                            v = session.get(meta, id);
                        }
                        if (v != null) {
                            objects.add(v);
                        }
                    }
                } finally {
                    if (session != null) {
                        session.close();
                    }
                }
            }
            metadata.setPropertyValue(object, property, objects);
        }
        metadata.setPropertyValue(object, property, Beans.toObject(meta, value));
    }

    /**
     * 设置对象属性值
     *
     * @param sessionFactory 会话工厂
     * @param object         对象实例
     * @param parameters     属性名称/值键值对
     */
    public static void setValues(SessionFactory sessionFactory, Object object, Map parameters) {
        if (object != null && parameters != null && !parameters.isEmpty()) {
            for (Entry entry : parameters.entrySet()) {
                setValue(sessionFactory, object, entry.getKey(), entry.getValue());
            }
        }
    }

    /**
     * 获取数据查询对象
     *
     * @param             数据类型
     * @param sessionFactory 会话工厂
     * @param model          数据模型
     * @return 数据查询对象
     */
    public static  Query query(SessionFactory sessionFactory, Class model) {
        if (sessionFactory == null) {
            throw new IllegalArgumentException("SessionFactory must not be null");
        }
        if (model == null) {
            throw new IllegalArgumentException("Model must not be null");
        }
        return new DetachedCriteriaQuery(sessionFactory, model);
    }

    /**
     * 创建数据持久层代码
     *
     * @param packages 数据模型所在包
     */
    public static void createRepositoryResource(String... packages) {
        for (String pack : packages) {
            createRepositoryResource(Beans.getClasses(pack).toArray(new Class[0]));
        }
    }

    /**
     * 创建数据持久层代码
     *
     * @param models 数据模型数组
     */
    public static void createRepositoryResource(Class... models) {
        for (Class model : models) {
            if (Beans.isMetaClass(model) || Modifier.isAbstract(model.getModifiers())) {
                continue;
            }
            File resourcePath;
            try {
                resourcePath = new File(new File(URLDecoder.decode(System.getProperty("user.dir"), "utf-8")), "src");
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            String pack = model.getPackage().getName();
            String basePack = pack.substring(0, pack.lastIndexOf("."));
            File repositoryInterfacePath = new File(new File(resourcePath, Strings.replace(basePack, '.', '/')),
                "repository");
            if (!repositoryInterfacePath.exists()) {
                repositoryInterfacePath.mkdirs();
            }
            String repositoryInterfaceName = model.getSimpleName() + "Repository";
            File repositoryInterface = new File(repositoryInterfacePath, repositoryInterfaceName + ".java");
            if (!repositoryInterface.exists()) {
                BufferedWriter writer = null;
                try {
                    writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(repositoryInterface),
                        "utf-8"));
                    writer.write("package " + basePack + ".repository;");
                    writer.newLine();
                    writer.newLine();
                    writer.write("import ars.database.repository.Repository;");
                    writer.newLine();
                    writer.newLine();
                    writer.write("import " + model.getName() + ";");
                    writer.newLine();
                    writer.newLine();
                    writer.write("/**");
                    writer.newLine();
                    writer.write(" * " + model.getSimpleName() + " repository interface");
                    writer.newLine();
                    writer.write(" *");
                    writer.newLine();
                    writer.write(" * @author " + System.getenv().get("USERNAME"));
                    writer.newLine();
                    writer.write(" *");
                    writer.newLine();
                    writer.write(" */");
                    writer.newLine();
                    writer.write("public interface " + repositoryInterfaceName + " extends Repository<"
                        + model.getSimpleName() + "> {");
                    writer.newLine();
                    writer.newLine();
                    writer.write("}");
                    writer.newLine();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                } finally {
                    if (writer != null) {
                        try {
                            writer.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }

            File repositoryImplementPath = new File(repositoryInterfacePath, "impl");
            if (!repositoryImplementPath.exists()) {
                repositoryImplementPath.mkdirs();
            }
            File repositoryImplement = new File(repositoryImplementPath, repositoryInterfaceName + "Impl.java");
            if (!repositoryImplement.exists()) {
                BufferedWriter writer = null;
                try {
                    writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(repositoryImplement),
                        "utf-8"));
                    writer.write("package " + basePack + ".repository.impl;");
                    writer.newLine();
                    writer.newLine();
                    writer.write("import org.springframework.stereotype.Repository;");
                    writer.newLine();
                    writer.newLine();
                    writer.write("import ars.database.hibernate.HibernateSimpleRepository;");
                    writer.newLine();
                    writer.newLine();
                    writer.write("import " + model.getName() + ";");
                    writer.newLine();
                    writer.write("import " + basePack + ".repository." + repositoryInterfaceName + ";");
                    writer.newLine();
                    writer.newLine();
                    writer.write("@Repository");
                    writer.newLine();
                    writer.write("public class " + repositoryInterfaceName + "Impl extends HibernateSimpleRepository<"
                        + model.getSimpleName() + "> implements " + repositoryInterfaceName + " {");
                    writer.newLine();
                    writer.newLine();
                    writer.write("}");
                    writer.newLine();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                } finally {
                    if (writer != null) {
                        try {
                            writer.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }

    /**
     * 创建实体映射配置文件
     *
     * @param packages 数据模型所在包
     */
    public static void createEntityConfigure(String... packages) {
        for (String pack : packages) {
            createEntityConfigure(Beans.getClasses(pack).toArray(new Class[0]));
        }
    }

    /**
     * 将驼峰式字符串以“_”号进行拆分
     *
     * @param source 被拆分源字符串
     * @return 拆分后字符串
     */
    private static String getNameString(String source) {
        StringBuilder chars = new StringBuilder();
        for (int i = 0; i < source.length(); i++) {
            char c = source.charAt(i);
            if (Character.isUpperCase(c)) {
                if (i > 0) {
                    chars.append('_');
                }
                chars.append(c);
            } else {
                chars.append(Character.toUpperCase(c));
            }
        }
        return chars.toString();
    }

    /**
     * 创建实体映射配置文件
     *
     * @param models 数据模型数组
     */
    public static void createEntityConfigure(Class... models) {
        for (Class model : models) {
            if (Beans.isMetaClass(model) || Modifier.isAbstract(model.getModifiers())) {
                continue;
            }
            File resourcePath;
            try {
                resourcePath = new File(new File(URLDecoder.decode(System.getProperty("user.dir"), "utf-8")), "src");
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            String pack = model.getPackage().getName();
            File configurePath = new File(new File(resourcePath, Strings.replace(pack, '.', '/')), "hbm");
            if (!configurePath.exists()) {
                configurePath.mkdirs();
            }
            File configure = new File(configurePath, model.getSimpleName() + ".hbm.xml");
            if (!configure.exists()) {
                BufferedWriter writer = null;
                try {
                    writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(configure), "utf-8"));
                    writer.write("");
                    writer.newLine();
                    writer.write("");
                    writer.newLine();
                    writer.write("");
                    writer.newLine();
                    writer.write("\t");
                    writer.newLine();
                    writer.write("\t\t");
                    writer.newLine();
                    writer.write("\t\t\t");
                    writer.newLine();
                    writer.write("\t\t");

                    Class _model = model;
                    while (_model != Object.class) {
                        Field[] fields = _model.getDeclaredFields();
                        for (Field field : fields) {
                            if (!Modifier.isStatic(field.getModifiers())) {
                                String name = field.getName();
                                Class type = field.getType();
                                if (type == Object.class || name.equals("id")) {
                                    continue;
                                }
                                String column = getNameString(name);
                                if (type == byte.class || type == Byte.class) {
                                    writer.newLine();
                                    writer.write("\t\t");
                                } else if (type == byte[].class || type == Byte[].class) {
                                    writer.newLine();
                                    writer.write("\t\t");
                                } else if (type == int.class || type == Integer.class) {
                                    writer.newLine();
                                    if ((Model.class.isAssignableFrom(model) && name.equals("status"))
                                        || (TreeModel.class.isAssignableFrom(model) && name.equals("level"))) {
                                        writer.write("\t\t");
                                    } else {
                                        writer.write("\t\t");
                                    }
                                } else if (type == short.class || type == Short.class) {
                                    writer.newLine();
                                    writer.write("\t\t");
                                } else if (type == float.class || type == Float.class) {
                                    writer.newLine();
                                    writer.write("\t\t");
                                } else if (type == double.class || type == Double.class) {
                                    writer.newLine();
                                    writer.write("\t\t");
                                } else if (type == long.class || type == Long.class) {
                                    writer.newLine();
                                    writer.write("\t\t");
                                } else if (type == boolean.class || type == Boolean.class) {
                                    writer.newLine();
                                    if ((Model.class.isAssignableFrom(model) && name.equals("active"))
                                        || (TreeModel.class.isAssignableFrom(model) && (name.equals("leaf")))) {
                                        writer.write("\t\t");
                                    } else {
                                        writer.write("\t\t");
                                    }
                                } else if (type == char.class || type == Character.class) {
                                    writer.newLine();
                                    writer.write("\t\t");
                                } else if (type == String.class) {
                                    writer.newLine();
                                    if (TreeModel.class.isAssignableFrom(model) && name.equals("key")) {
                                        writer.write("\t\t");
                                    } else {
                                        writer.write("\t\t");
                                    }
                                } else if (Date.class.isAssignableFrom(type)) {
                                    writer.newLine();
                                    if (Model.class.isAssignableFrom(model) && name.equals("dateJoined")) {
                                        writer.write("\t\t");
                                    } else {
                                        writer.write("\t\t");
                                    }
                                } else if (Enum.class.isAssignableFrom(type)) {
                                    writer.newLine();
                                    writer.write("\t\t");
                                    writer.newLine();
                                    writer.write("\t\t\t");
                                    writer.newLine();
                                    writer.write("\t\t\t\t" + type.getName() + "");
                                    writer.newLine();
                                    writer.write("\t\t\t");
                                    writer.newLine();
                                    writer.write("\t\t");
                                } else if (Collection.class.isAssignableFrom(type)) {
                                    Class foreign = null;
                                    Class[] genericTypes = Beans.getGenericTypes(field);
                                    if (genericTypes.length == 0 || (foreign = genericTypes[0]) == Object.class
                                        || Modifier.isAbstract(foreign.getModifiers())) {
                                        continue;
                                    }
                                    writer.newLine();
                                    if (Set.class.isAssignableFrom(type)) {
                                        writer.write("\t\t");
                                    } else {
                                        writer.write("\t\t");
                                    }
                                    writer.newLine();
                                    writer.write("\t\t\t");
                                    if (List.class.isAssignableFrom(type)) {
                                        writer.newLine();
                                        writer.write("\t\t\t");
                                    }
                                    writer.newLine();
                                    if (Beans.isMetaClass(foreign)) {
                                        writer.write("\t\t\t");
                                    } else {
                                        writer.write("\t\t\t");
                                    }
                                    writer.newLine();
                                    if (Set.class.isAssignableFrom(type)) {
                                        writer.write("\t\t");
                                    } else {
                                        writer.write("\t\t");
                                    }
                                } else if (!Modifier.isAbstract(type.getModifiers())) {
                                    writer.newLine();
                                    writer.write("\t\t");
                                }
                            }
                        }
                        _model = _model.getSuperclass();
                    }
                    if (TreeModel.class.isAssignableFrom(model)) {
                        writer.newLine();
                        writer.write("\t\t");
                        writer.newLine();
                        writer.write("\t\t");
                        writer.newLine();
                        writer.write("\t\t\t");
                        writer.newLine();
                        writer.write("\t\t\t");
                        writer.newLine();
                        writer.write("\t\t\t");
                        writer.newLine();
                        writer.write("\t\t");
                    }
                    writer.newLine();
                    writer.write("\t");
                    writer.newLine();
                    writer.write("");
                } catch (IOException e) {
                    throw new RuntimeException(e);
                } finally {
                    if (writer != null) {
                        try {
                            writer.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }

}