本文主要给大家介绍下如何利用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");
}
}