使用Hibernate实现数据模型功能

         本文主要给大家介绍下如何利用hibernate对数据表的管理来实现一个数据模型管理功能。

数据模型表

CREATE TABLE `table_model` (
  `id` varchar(64) COLLATE utf8_bin NOT NULL COMMENT '主键ID',
  `table_name` varchar(100) COLLATE utf8_bin DEFAULT NULL COMMENT '数据表名',
  `model_name` varchar(200) COLLATE utf8_bin DEFAULT NULL COMMENT '模型名称',
  `table_remark` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '模型描述',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='数据模型表';

 数据模型列定义表

CREATE TABLE `table_model_column` (
  `id` varchar(64) COLLATE utf8_bin NOT NULL,
  `model_id` varchar(64) COLLATE utf8_bin DEFAULT NULL COMMENT '数据模型表ID',
  `column_name` varchar(100) COLLATE utf8_bin DEFAULT NULL COMMENT '列表名',
  `column_remark` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '列描述',
  `column_type` varchar(255) COLLATE utf8_bin DEFAULT NULL COMMENT '列表类型',
  `column_length` int(11) DEFAULT NULL COMMENT '列长度',
  `prop_name` varchar(100) COLLATE utf8_bin DEFAULT NULL COMMENT '对应表单属性名',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='数据模型列定义表';

主要用到的是Hibernate的动态模型功能。

定义映射模板文件并命名【template.hb.ftl】,放到咱们工程的resource目录下。

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE hibernate-mapping   PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class entity-name="${entity.modelName}" table="${entity.tableName}" dynamic-update="true">
        <comment>${entity.tableRemark}</comment>
        <#if entity.tableModelColumnList?exists>
            <id name="id" type="java.lang.String" unsaved-value="null">
                <column name="id" length="64" >
                    <comment>主键</comment>
                </column>
                <generator class="com.breeze.form.config.GeneralId" />
            </id>
            <#list entity.tableModelColumnList as attr>
                <#if attr.columnName == "id">

                <#else>
                    <property name="${attr.propName}" type="${attr.columnType}" access="property" update="true"
                              insert="true">
                        <column name="${attr.columnName}"
                                not-null="false"
                                length="${attr.columnLength}"
                                unique="false"
                        >
                            <comment>${attr.columnRemark}</comment>
                        </column>
                    </property>
                </#if>
            </#list>
        </#if>
    </class>
</hibernate-mapping>

数据模型增删除改相关代码

Map<String, Object> paramMap = new HashMap<>();
paramMap.put("entity", tableModel);
Template template = getTemplateConfig("/templates").getTemplate("template.hb.ftl");
Writer out = new StringWriter();
template.process(paramMap, out);

SessionFactory sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);
StandardServiceRegistry serviceRegistry = sessionFactory.getSessionFactoryOptions().getServiceRegistry();
MetadataSources metadataSources = new MetadataSources(serviceRegistry);
sessionFactory.getSessionFactoryOptions();

        //读取映射文件
metadataSources.addInputStream(new ByteArrayInputStream(out.toString().getBytes()));
Metadata metadata = metadataSources.buildMetadata();

if (FlushType.delete.equals(flushType)) {
   SchemaExport schemaExport = new SchemaExport();
   schemaExport.drop(EnumSet.of(TargetType.DATABASE), metadata);
} else if (FlushType.create.equals(flushType)) {
   SchemaExport schemaExport = new SchemaExport();
   schemaExport.create(EnumSet.of(TargetType.DATABASE), metadata);
} else {
   Session session = metadata.buildSessionFactory().openSession();
   NativeQuery nativeQuery = session.createNativeQuery("select count(1) from " + tableModel.getTableName());
   if (G.l(nativeQuery.getSingleResult()) > 0) {
        SchemaUpdate schemaUpdate = new SchemaUpdate();
        schemaUpdate.execute(EnumSet.of(TargetType.DATABASE), metadata);
   } else {
        SchemaExport schemaExport = new SchemaExport();
        schemaExport.create(EnumSet.of(TargetType.DATABASE), metadata);
   }
        session.close();
}

新增更新模型数据

Map<String, Object> paramMap = new HashMap<>();
paramMap.put("entity", tableModel);
Template template = getTemplateConfig("/templates").getTemplate("template.hb.ftl");
Writer out = new StringWriter();
template.process(paramMap, out);

SessionFactory sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);
StandardServiceRegistry serviceRegistry = sessionFactory.getSessionFactoryOptions().getServiceRegistry();
MetadataSources metadataSources = new MetadataSources(serviceRegistry);
sessionFactory.getSessionFactoryOptions();

        //读取映射文件
metadataSources.addInputStream(new ByteArrayInputStream(out.toString().getBytes()));
Metadata metadata = metadataSources.buildMetadata();
SessionFactory newSessionFactory = metadata.buildSessionFactory();
Session newSession = newSessionFactory.openSession();
Transaction tx = newSession.beginTransaction();
newSession.saveOrUpdate(tableModel.getModelName(), formData);
tx.commit();
newSession.close();

删除模型数据

Map<String, Object> paramMap = new HashMap<>();
paramMap.put("entity", tableModel);
Template template = getTemplateConfig("/templates").getTemplate("template.hb.ftl");
Writer out = new StringWriter();
template.process(paramMap, out);

SessionFactory sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);
StandardServiceRegistry serviceRegistry = sessionFactory.getSessionFactoryOptions().getServiceRegistry();
MetadataSources metadataSources = new MetadataSources(serviceRegistry);
sessionFactory.getSessionFactoryOptions();

        //读取映射文件
metadataSources.addInputStream(new ByteArrayInputStream(out.toString().getBytes()));
Metadata metadata = metadataSources.buildMetadata();
SessionFactory newSessionFactory = metadata.buildSessionFactory();
Session newSession = newSessionFactory.openSession();
Transaction tx = newSession.beginTransaction();
String sql = "delete from " + tableModel.getModelName() + " t where t.id=:id";
Query query = newSession.createQuery(sql);
query.setParameter("id", dataId);
query.executeUpdate();
tx.commit();
newSession.close();

查询模型数据

Map<String, Object> paramMap = new HashMap<>();
paramMap.put("entity", tableModel);
Template template = getTemplateConfig("/templates").getTemplate("template.hb.ftl");
Writer out = new StringWriter();
template.process(paramMap, out);

SessionFactory sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);
StandardServiceRegistry serviceRegistry = sessionFactory.getSessionFactoryOptions().getServiceRegistry();
MetadataSources metadataSources = new MetadataSources(serviceRegistry);
sessionFactory.getSessionFactoryOptions();

        //读取映射文件
metadataSources.addInputStream(new ByteArrayInputStream(out.toString().getBytes()));
Metadata metadata = metadataSources.buildMetadata();
SessionFactory newSessionFactory = metadata.buildSessionFactory();
Session newSession = newSessionFactory.openSession();
String sql = "from " + tableModel.getModelName() + " t where t.id=:id";
Query query = newSession.createQuery(sql);
query.setParameter("id", dataId);
query.setReadOnly(true);
Object result = query.uniqueResult();
newSession.close();

上面代码为了演示单个代码版本有些冗余,大家实际使用需要提取,而且实际使用过程中不能每次去buildsessionfactory,下面展示一下

package com.breeze.form.util;

import com.breeze.form.mybatis.domain.TableModel;
import com.breeze.form.mybatis.mapper.TableModelMapper;
import com.breeze.form.service.TableModelService;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.internal.SessionFactoryImpl;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.persistence.EntityManagerFactory;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static freemarker.template.Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS;

/**
 * @author breeze
 * @since 2022/8/30 15:55
 */
@Component
@Scope("singleton")
@Slf4j
public class TableModelSessionFactory implements InitializingBean {
    @Autowired
    EntityManagerFactory entityManagerFactory;
    @Resource
    TableModelService tableModelService;

    Template template;

    SessionFactoryImpl sessionFactory;
    StandardServiceRegistry serviceRegistry;


    public void init() {
        List<TableModel> tableModels = tableModelService.selectAll();
        MetadataSources metadataSources = new MetadataSources(serviceRegistry);
        tableModels.stream().map(a -> tableModelService.info(a.getId())).forEach(a -> addTableModel(a, metadataSources));

        sessionFactory.addMetadata((MetadataImplementor) metadataSources.buildMetadata());
    }


    public Session getSession() {
        return sessionFactory.openSession();
    }

    public void loadTableModel(TableModel tableModel) throws IOException, TemplateException {
        log.info("table model session factory load table model:[" + tableModel.getTableName() + "]");
        MetadataSources metadataSources = new MetadataSources(serviceRegistry);
        addTableModel(tableModel, metadataSources);

        sessionFactory.addMetadata((MetadataImplementor) metadataSources.buildMetadata());

        sessionFactory.getQueryPlanCache().cleanup();
    }

    @SneakyThrows
    private void addTableModel(TableModel tableModel, MetadataSources metadataSources) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("entity", tableModel);
        Writer out = new StringWriter();
        template.process(paramMap, out);
        metadataSources.addInputStream(new ByteArrayInputStream(out.toString().getBytes()));
    }

    public Metadata loadMetadata(TableModel tableModel) throws IOException, TemplateException {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("entity", tableModel);
        Writer out = new StringWriter();
        template.process(paramMap, out);
        SessionFactory sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);
        StandardServiceRegistry serviceRegistry = sessionFactory.getSessionFactoryOptions().getServiceRegistry();
        MetadataSources metadataSources = new MetadataSources(serviceRegistry);
        //读取映射文件
        metadataSources.addInputStream(new ByteArrayInputStream(out.toString().getBytes()));

        Metadata result = metadataSources.buildMetadata();
        return result;
    }

    protected freemarker.template.Configuration getTemplateConfig(String resource) {
        freemarker.template.Configuration cfg = new freemarker.template.Configuration(DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
        cfg.setDefaultEncoding("UTF-8");
        cfg.setClassForTemplateLoading(this.getClass(), resource);
        return cfg;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        sessionFactory = entityManagerFactory.unwrap(SessionFactoryImpl.class);
        serviceRegistry = sessionFactory.getSessionFactoryOptions().getServiceRegistry();

        template = getTemplateConfig("/templates").getTemplate("template.hb.ftl");
    }


}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

eclipsewangwfUN

棋盘内,车无轮马无缰,叫声将军

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值