官网地址
PDMan数据库建模
PDManer(元数建模)是一款功能强大且易于使用的开源数据库建模工具
一、主要特点
- 多数据库支持:PDManer支持多种常见数据库,如MySQL、PostgreSQL、Oracle、SQL Server等,还特别支持国产数据库如达梦、GuassDB等,以及Hive、MaxCompute等大数据方向的数据库。用户还可以自行添加更多的数据库扩展。
- 跨平台兼容:PDManer支持Windows、Mac、Linux等多种操作系统,甚至支持国产操作系统,具有广泛的适用性。
- 集成多项功能:PDManer集成了数据表管理、视图生成、ER图绘制、数据字典管理和代码生成等多项功能,旨在帮助开发者更高效地进行数据库设计和项目开发。
二、功能详解
- 数据表管理:支持多种数据库的数据表管理,确保数据的统一性和一致性。用户可以通过右键点击工作区,选择“新建表”来创建一个新的数据表,并设置表名、主键、字段等信息。PDManer支持多种数据类型,如整数、字符串、日期等,并提供了字段注释、默认值等功能,方便用户进行表设计。
- 视图生成:自动生成数据库视图,简化开发流程,提高开发效率。用户可以通过右键点击工作区,选择“新建视图”来创建一个新的视图,并设置视图名、查询语句等信息。PDManer支持SQL语法高亮显示和自动补全功能,方便用户编写查询语句。
- ER图绘制:通过实体关系图(ER图)的绘制,帮助用户更好地理解数据库结构,便于团队协作和项目管理。用户可以通过右键点击工作区,选择“新建关系图”来创建一个新的关系图,并将需要展示关系的表添加到关系图中,通过连线来表示它们之间的关系。PDManer支持多种关系类型,如一对一、一对多、多对多等。
- 数据字典管理:方便管理数据库中的数据字典,确保数据的一致性和准确性。用户可以通过右键点击工作区,选择“新建数据字典”来创建一个新的数据字典,并添加表、字段、数据类型等元数据信息。
- 代码生成:根据数据库模型自动生成代码,减少手动编写代码的工作量,提高开发效率。用户需要定义数据源和模板,然后选择合适的代码类型和输出路径,点击“开始”按钮,PDManer即可根据模板和数据源自动生成代码。
三、应用场景
- 中小型项目开发:PDManer的易用性和简洁界面使其成为中小型项目开发的理想选择。
- 数据库设计与管理:无论是初学者还是资深开发者,PDManer都能帮助他们高效地进行数据库设计和数据管理。
- 团队协作:通过ER图的绘制和数据字典的管理,PDManer有助于团队成员更好地理解和协作,确保项目的高质量交付。
四、技术架构与更新
PDManer基于ES6+React+Electron+Java构建,技术架构设计合理。自发布以来,PDManer经历了多个版本的迭代更新,不断优化和提升用户体验。例如,PDManer v4.1.0版本就增加了字段扩展属性、优化了表头设置、改进了启动界面和系统设置等。
实例创建
1.Entity
{{ var today=new Date();
var fullYear=today.getFullYear();
var month=today.getMonth() + 1;
var days=today.getDate();
var pkVarName = "undefinedId";
var pkDataType = "String";
it.entity.fields.forEach(function(field){
if(field.primaryKey){
pkVarName = it.func.camel(field.defKey,false);
pkDataType = field["type"];
return;
}
});
var pkgName = it.entity.env.base.nameSpace;
var beanClass = it.entity.env.base.codeRoot;
var beanVarName = beanClass.charAt(0).toLowerCase()+beanClass.slice(1);
var serviceClass = beanClass+'Service';
var serviceVarName= beanVarName+'Service';
}}package {{=pkgName}}.entity;
$blankline
import java.time.LocalDateTime;
import lombok.Data;
import java.math.BigDecimal;
$blankline
/**
* {{=it.entity.defName}};{{=it.entity.comment}}
* @author : heimi
* @date : {{=fullYear}}-{{=month}}-{{=days}}
*/
@Data
public class {{=beanClass}} extends BaseEntity {
{{~it.entity.fields:field:index}}
/** {{=it.func.join(field.defName,field.comment,';')}} */
private {{=field.type}} {{=it.func.camel(field.defKey,false)}} ;
{{~}}
$blankline
}
2.Dao
{{ var today=new Date();
var fullYear=today.getFullYear();
var month=today.getMonth() + 1;
var days=today.getDate();
var pkVarName = "undefinedId";
var pkDataType = "String";
it.entity.fields.forEach(function(field){
if(field.primaryKey){
pkVarName = it.func.camel(field.defKey,false);
pkDataType = field["type"];
return;
}
});
var pkgName = it.entity.env.base.nameSpace;
var beanClass = it.entity.env.base.codeRoot;
var beanVarName = beanClass.charAt(0).toLowerCase()+beanClass.slice(1);
var serviceClass = beanClass+'Service';
var serviceVarName= beanVarName+'Service';
}}package {{=pkgName}}.mapper;
$blankline
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.data.domain.Pageable;
import {{=pkgName}}.model.{{=beanClass}};
$blankline
/**
* {{=it.entity.defName}};({{=it.entity.defKey}})表数据库访问层
* @author : heimi
* @date : {{=fullYear}}-{{=month}}-{{=days}}
*/
@Mapper
public interface {{=beanClass}}Dao{
@PageX
List<{{=beanClass}}> select({{=beanClass}}Query query);
Integer insert({{=beanClass}} {{=beanVarName}});
Integer insertBatch(List<{{=beanClass}}> {{=beanVarName}}s);
Integer update({{=beanClass}} {{=beanVarName}});
Integer delete(Integer id);
}
3.Service
{{ var today=new Date();
var fullYear=today.getFullYear();
var month=today.getMonth() + 1;
var days=today.getDate();
var pkVarName = "undefinedId";
var pkVarNameU = "UndefinedId";
var pkDataType = "String";
it.entity.fields.forEach(function(field){
if(field.primaryKey){
pkVarName = it.func.camel(field.defKey,false);
pkVarNameU = it.func.camel(field.defKey,true);
pkDataType = field["type"];
return;
}
});
var pkgName = it.entity.env.base.nameSpace;
var beanClass = it.entity.env.base.codeRoot;
var beanVarName = beanClass.charAt(0).toLowerCase()+beanClass.slice(1);
var serviceClass = beanClass+'Service';
var serviceVarName= beanVarName+'Service';
var daoName = beanVarName+'Dao';
}}package {{=pkgName}}.service;
$blankline
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import {{=pkgName}}.entity.{{=beanClass}};
import {{=pkgName}}.dao.{{=beanClass}}Dao;
import {{=pkgName}}.service.{{=serviceClass}};
/**
* {{=it.entity.defName}};({{=it.entity.defKey}})表服务实现类
* @author : heimi
* @date : {{=fullYear}}-{{=month}}-{{=days}}
*/
@Service
public class {{=serviceClass}}{
$blankline
@Autowired
private {{=beanClass}}Dao {{=daoName}};
$blankline
public List<{{=beanClass}}> select({{=beanClass}}Query query) {
return {{=daoName}}.select(query);
}
$blankline
public Integer insert({{=beanClass}} {{=beanVarName}}) {
return {{=daoName}}.insert({{=beanVarName}});
}
$blankline
public Integer update({{=beanClass}} {{=beanVarName}}) {
return {{=daoName}}.update({{=beanVarName}});
}
$blankline
public Integer delete(Integer id) {
return {{=daoName}}.delete(id);
}
}
4.Controller
{{ var today=new Date();
var fullYear=today.getFullYear();
var month=today.getMonth() + 1;
var days=today.getDate();
var pkVarName = "undefinedId";
var pkDataType = "String";
it.entity.fields.forEach(function(field){
if(field.primaryKey){
pkVarName = it.func.camel(field.defKey,false);
pkDataType = field["type"];
return;
}
});
var pkgName = it.entity.env.base.nameSpace;
var beanClass = it.entity.env.base.codeRoot;
var beanVarName = beanClass.charAt(0).toLowerCase()+beanClass.slice(1);
var serviceClass = beanClass+'Service';
var serviceVarName= beanVarName+'Service';
}}package {{=pkgName}}.controller;
$blankline
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import {{=pkgName}}.model.{{=beanClass}};
import {{=pkgName}}.service.{{=serviceClass}};
$blankline
/**
* {{=it.entity.defName}};({{=it.entity.defKey}})控制层
* @author : heimi
* @date : {{=fullYear}}-{{=month}}-{{=days}}
*/
@RestController
@RequestMapping("/api/{{=beanVarName}}")
public class {{=beanClass}}Controller{
@Autowired
private {{=serviceClass}} {{=serviceVarName}};
$blankline
/**
* 查询接口
*/
@GetMapping
public List<{{=beanClass}}> select({{=beanClass}}Query query){
return {{=serviceVarName}}.select(query);
}
$blankline
@PostMapping
public Integer insert(@RequestBody {{=beanClass}} product){
return {{=serviceVarName}}.insert(product);
}
$blankline
@PutMapping
public Integer update(@RequestBody {{=beanClass}} product){
return {{=serviceVarName}}.update(product);
}
$blankline
@DeleteMapping
public Integer delete(Integer id){
return {{=serviceVarName}}.delete(id);
}
}
5.Mapper.xml
{{ var today=new Date();
var fullYear=today.getFullYear();
var month=today.getMonth() + 1;
var days=today.getDate();
var pkVarName = "undefinedId";
var pkDataType = "String";
var pkField = "UNDEFINED_ID";
it.entity.fields.forEach(function(field){
if(field.primaryKey){
pkField = field.defKey;
pkVarName = it.func.camel(field.defKey,false);
pkDataType = field["type"];
return;
}
});
var pkgName = it.entity.env.base.nameSpace;
var beanClass = it.entity.env.base.codeRoot;
var beanVarName = beanClass.charAt(0).toLowerCase()+beanClass.slice(1);
var serviceClass = beanClass+'Service';
var serviceVarName= beanVarName+'Service';
}}<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="{{=pkgName}}.mapper.{{=beanClass}}Mapper">
<resultMap type="{{=pkgName}}.model.{{=beanClass}}" id="{{=beanClass}}Map">
{{~it.entity.fields:field:index}}
<result property="{{=it.func.camel(field.defKey,false)}}" column="{{=field.defKey}}" />
{{~}}
</resultMap>
$blankline
$blankline
<!--通用查询-->
<select id="select" resultMap="{{=beanClass}}Map">
select
{{=it.entity.fields.map(function(e,i){return e.defKey}).join(',')}}
from {{=it.entity.defKey}}
<where>
{{~it.entity.fields:field:index}}
<if test="{{=it.func.camel(field.defKey,false)}} != null and {{=it.func.camel(field.defKey,false)}} != ''">
and {{=field.defKey}} = #{{{=it.func.camel(field.defKey,false)}}}
</if>
{{~}}
</where>
</select>
$blankline
<!--新增数据-->
<insert id="insert" keyProperty="{{=pkField}}" useGeneratedKeys="true">
insert into {{=it.entity.defKey}}({{=it.entity.fields.map(function(e,i){return e.defKey}).join(',')}})
values ({{=it.entity.fields.map(function(e,i){return '#{'+it.func.camel(e.defKey,false)+'}'}).join(',')}})
</insert>
$blankline
<!-- 批量新增数据 -->
<insert id="insertBatch" keyProperty="{{=pkField}}" useGeneratedKeys="true">
insert into {{=it.entity.defKey}}({{=it.entity.fields.map(function(e,i){return e.defKey}).join(',')}})
values
<foreach collection="entities" item="entity" separator=",">
({{=it.entity.fields.map(function(e,i){return '#{entity.'+it.func.camel(e.defKey,false)+'}'}).join(',')}})
</foreach>
</insert>
$blankline
<!-- 更新数据 -->
<update id="update">
update {{=it.entity.defKey}}
<set>
{{~it.entity.fields:field:index}}
<if test="{{=it.func.camel(field.defKey,false)}} != null and {{=it.func.camel(field.defKey,false)}} != ''">
{{=field.defKey}} = #{{{=it.func.camel(field.defKey,false)}}},
</if>
{{~}}
</set>
where {{=pkField}} = #{{{=pkVarName}}}
</update>
$blankline
<!--通过主键软删除-->
<update id="delete">
update {{=it.entity.defKey}} set status = 0 where {{=pkField}} = #{{{=pkVarName}}}
</update>
</mapper>