逆向工程

2020-03-20  本文已影响0人  拼搏男孩

逆向工程与EasyCode

一、基本概念

1、物理数据模型、逻辑数据模型与概念数据模型

数据模型所描述的内容包括三个部分:数据结构、数据操作、数据约束。

1)数据结构:数据模型中的数据结构主要描述数据的类型、内容、性质以及数据间的联系等。数据结构是数据模型的基础,数据操作和约束都建立在数据结构上。不同的数据结构具有不同的操作和约束。

2)数据操作:数据模型中数据操作主要描述在相应的数据结构上的操作类型和操作方式。

3)数据约束:数据模型中的数据约束主要描述数据结构内数据间的语法、词义联系、他们之间的制约和依存关系,以及数据动态变化的规则,以保证数据的正确、有效和相容。

数据模型按不同的应用层次分成三种类型:分别是概念数据模型、逻辑数据模型、物理数据模型。

1、概念数据模型(Conceptual Data Model):简称 概念模型 ,主要用来描述世界的概念化结构,它使数据库的设计人员在设计的初始阶段,摆脱计算机系统及DBMS的具体技术问题,集中精力分析数据以及数据之间的联系 等,与具体的数据管理系统(Database Management System,简称DBMS)无关。概念数据模型必须换成逻辑数据模型,才能在DBMS中实现。

概念数据模型是最终用户对数据存储的看法,反映了最终用户综合性的信息需求,它以数据类的方式描述企业级的数据需求,数据类代表了在业务环境中自然聚集成的几个主要类别数据。

概念数据模型的内容包括重要的 实体及实体之间的关系 。在概念数据模型中 不包括实体的属性 ,也 不用定义实体的主键 。这是概念数据模型和逻辑数据模型的主要区别。

概念数据模型的目标是统一业务概念,作为业务人员和技术人员之间沟通的桥梁,确定不同实体之间的最高层次的关系。

在有些数据模型的设计过程中,概念数据模型是和逻辑数据模型合在一起进行设计的。

2、逻辑数据模型(Logical Data Model):简称数据模型,这是用户从数据库所看到的模型,是具体的DBMS所支持的数据模型,如网状数据模型(Network Data Model)、 层次数据模型 (Hierarchical Data Model)等等。 此模型既要面向用户,又要面向系统 ,主要用于数据库管理系统 (DBMS)的实现。

逻辑数据模型 反映的是系统分析设计人员对数据存储的观点,是对概念数据模型进一步的分解和细化。 逻辑数据模型是根据业务规则确定的,关于业务对象、业务对象的数据项及业务对象之间关系的基本蓝图。

逻辑数据模型的 内容包括所有的实体和关系,确定每个实体的属性,定义每个实体的主键,指定实体的外键,需要进行范式化处理。

逻辑数据模型的目标是尽可能详细的描述数据,但并不考虑数据在物理上如何来实现。

逻辑数据建模不仅会影响数据库设计的方向,还间接影响最终数据库的性能和管理。如果在实现逻辑数据模型时投入得足够多,那么在物理数据模型设计时就可以有许多可供选择的方法。

3、物理数据模型(Physical Data Model):简称 物理模型 ,是面向计算机物理表示的模型,描述了数据在储存介质上的组织结构,它不但与具体的DBMS 有关,而且还与操作系统和硬件有关。每一种逻辑数据模型在实现时都有起对应的物理数据模型。DBMS为了保证其独立性与可移植性,大部分物理数据模型的实 现工作又系统自动完成,而设计者只设计索引、聚集等特殊结构。

在概念数据模型中最常用的是 E-R模型、扩充的E-R模型、面向对象模型及谓词模型。在逻辑数据类型中最常用的是 层次模型 、 网状模型 、 关系模型。

物理数据模型是在逻辑数据模型的基础上,考虑各种具体的技术实现因素,进行数据库体系结构设计,真正实现数据在数据库中的存放。

物理数据模型的内容包括确定所有的表和列,定义外键用于确定表之间的关系,基于用户的需求可能进行发范式化等内容。在物理实现上的考虑,可能会导致物理数据模型和逻辑数据模型有较大的不同。

物理数据模型的目标是指定如何用数据库模式来实现逻辑数据模型,以及真正的保存数据。

2、逆向工程

软件逆向工程(Software Reverse Engineering)又称软件反向工程,是指从可运行的程序系统出发,运用解密、反汇编、系统分析、程序理解等多种计算机技术,对软件的结构、流程、算法、代码等进行逆向拆解和分析,推导出软件产品的源代码、设计原理、结构、算法、处理过程、运行方法及相关文档等。通常,人们把对软件进行反向分析的整个过程统称为软件逆向工程,把在这个过程中所采用的技术都统称为软件逆向工程技术。在现阶段的学习中,逆向工程指的是由数据库表生成pojo、dao与mapper。

二、逆向工程的实现

1、PowerDesigner的使用

PowerDesigner是一款十分强大的建模软件可以生成物理数据模型、逻辑数据模型概念数据模型、面向对象模型、以及xml约束。物理数据模型指的是数据库的表,这里可以用图形化的方法生成sql脚本文件并导出,还可以生成测试数据。概念模型指的是ER图,在ER图中存在着一对一、一对多、多对多的关系。面向对象模型可以由一张张表生成对应的pojo。可以生成不同语言的代码直接运行,不过要进行适当的调整。

2、mybatis-generator生成pojo、mapper文件与接口

在IDEA中使用插件可以根据数据库表自动生成pojo、mapper文件与接口。

首先,需要在pom.xml中添加一个插件:

<plugin>
    <groupId>org.mybatis.generator</groupId>
    <artifactId>mybatis-generator-maven-plugin</artifactId>
    <version>1.3.5</version>

    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.15</version>
        </dependency>
    </dependencies>

    <configuration>
        <!--配置文件的路径-->
        <configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
        <verbose>true</verbose>
        <overwrite>true</overwrite>
    </configuration>
</plugin>

这个插件和Tomcat插件平齐,引入了一个mysql的依赖,设置了配置文件的路径。generatorConfig.xml这个文件在resources的直接子目录下。

然后配置generatorConfig.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
    <properties resource="db.properties"/>
    <context id="generatorTables" targetRuntime="MyBatis3">
        <!-- genenate entity时,生成toString -->
        <plugin type="org.mybatis.generator.plugins.ToStringPlugin" />
        <plugin type="org.mybatis.generator.plugins.SerializablePlugin"/>
        <commentGenerator>
            <!-- 是否去除自动生成的注释 true:是 : false:否 -->
            <property name="suppressAllComments" value="true"/>
        </commentGenerator>

        <!--mysql数据库连接的信息:驱动类、连接地址、用户名、密码 -->
        <jdbcConnection driverClass="${driver}"
                        connectionURL="${url}"
                        userId="${user}"
                        password="${pass}">
            <!-- connectionURL属性,防止乱码 -->
            <property name="useUnicode" value="true"/>
            <!-- connectionURL属性,防止乱码 -->
            <property name="characterEncoding" value="utf-8"/>
            <!-- connectionURL属性,防止报时间错误 -->
            <property name="serverTimezone" value="UTC"/>
            <!-- connectionURL属性,防止生成不同数据库同名表的代码 -->
            <property name="nullCatalogMeansCurrent" value="true"/>
        </jdbcConnection>
        <!--oracle数据库连接的信息-->
        <!--<jdbcConnection driverClass="oracle.jdbc.OracleDriver"-->
        <!--connectionURL="jdbc:oracle:thin:@127.0.0.1:1521:yycg"-->
        <!--userId="yycg"-->
        <!--password="yycg">-->
        <!--</jdbcConnection>-->

        <!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer true,把JDBC DECIMAL 和NUMERIC 类型解析为java.math.BigDecimal -->
        <javaTypeResolver>
            <property name="forceBigDecimals" value="false"/>
        </javaTypeResolver>

        <!-- targetProject:自动生成代码的位置 -->
        <javaModelGenerator targetPackage="com.qianfeng.pojo"
                            targetProject=".\src\main\java">

            <!-- enableSubPackages:是否让schema作为包的后缀 -->
            <property name="enableSubPackages" value="false"/>

            <!-- 从数据库返回的值被清理前后的空格 -->
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>

        <!-- targetPackage:mapper映射文件生成的位置 -->
        <sqlMapGenerator targetPackage="com.qianfeng.mapper"
                         targetProject=".\src\main\resources">
            <property name="enableSubPackages" value="false"/>
        </sqlMapGenerator>

        <!-- targetPackage:mapper接口的生成位置 -->
        <javaClientGenerator type="XMLMAPPER"
                             targetPackage="com.qianfeng.mapper"
                             targetProject=".\src\main\java">
            <property name="enableSubPackages" value="false"/>
        </javaClientGenerator>


        <table schema="" tableName="user">
            <!--            <columnOverride column="customer_id" javaType="java.lang.Integer"/>-->
            <!--            <columnOverride column="customer_code" javaType="java.lang.String"/>-->
            <!--            <columnOverride column="username" javaType="java.lang.String"/>-->
            <!--            <columnOverride column="gender" javaType="java.lang.Byte"/>-->
            <!--            <columnOverride column="age" javaType="java.lang.Integer"/>-->
        </table>
        <table tableName="orders" schema=""/>
        <table tableName="address" schema=""/>
        <table tableName="order_item" schema=""/>
        <table tableName="product" schema=""/>
        <table tableName="pay_type" schema=""/>
        <table tableName="product_type" schema=""/>
        <table tableName="image" schema=""/>
    </context>
</generatorConfiguration>

需要修改的有五个地方,第一个地方是jdbcConnection,配置了数据库连接的信息,我是从properties文件中直接导入的,第二个地方是avaModelGenerator,这是生成的pojo的所在的目录,第三个地方是sqlMapGenerator,则是mapper映射文件所在的目录,第四个地方是javaClientGenerator,这是mapper接口所在的目录,第五个地方是table,指定了数据库的表。

注意:这个设置有一个非常坑的地方,默认会扫描当前连接所有数据库下同名的表,所以生成的mapper映射文件会有重复的id,导致运行报错,解决这种问题在connectionURL后面添加一个nullCatalogMeansCurrent=true就行了,有两种方式实现:

<!-- 数据库链接驱动、地址、用户名、密码 -->
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/testdemo" userId="root" password="root">
    <!-- connectionURL属性,防止乱码 -->
    <property name="useUnicode" value="true"/>
    <!-- connectionURL属性,防止乱码 -->
    <property name="characterEncoding" value="utf-8"/>
    <!-- connectionURL属性,防止报时间错误 -->
    <property name="serverTimezone" value="UTC"/>
    <!-- connectionURL属性,防止生成不同数据库同名表的代码 -->
    <property name="nullCatalogMeansCurrent" value="true"/>
</jdbcConnection>

或者是这样:

<!-- 数据库链接驱动、地址、用户名、密码 -->
<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/testdemo?useUnicode=true&amp;characterEncoding=utf-8&amp;serverTimezone=UTC&amp;nullCatalogMeansCurrent=true" userId="root" password="root">
</jdbcConnection>

3、Easy Code的使用

Easy Code是IDEA中的一个插件,非常好用,不仅能自动生成dao与mapper文件和pojo,还能自动生成controller与service,功能十分强大。但是要注意一个问题:easy code会在resources下生成mapper文件夹以及dao的xml文件,注意手动将其配置在与dao接口平级的resources目录下

三、分页

方式一:
@RequestParam注解用于从前台获取参数,value是参数的名称,defaultValue是默认值

package com.qianfeng.controller;

import com.qianfeng.entity.User;
import com.qianfeng.service.UserService;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.List;

/**
 * (User)表控制层
 *
 * @author makejava
 * @since 2020-03-20 11:00:53
 */
@RestController
@RequestMapping("user")
public class UserController {
    /**
     * 服务对象
     */
    @Resource
    private UserService userService;

    /**
     * 通过主键查询单条数据
     *
     * @param id 主键
     * @return 单条数据
     */
    @GetMapping("selectOne/{id}")
    public User selectOne(@PathVariable Integer id) {
        return this.userService.queryById(id);
    }
    @GetMapping("selectMore")
    public List<User> selectMore(@RequestParam(value = "currentPage",defaultValue = "1") int currentPage,
                                 @RequestParam(value = "pageSize",defaultValue = "5") int pageSize){
        if (currentPage<1){
            currentPage = 1;
        }
        if(pageSize<1){
            pageSize = 5;
        }
        List<User> users = userService.queryAllByLimit((currentPage - 1) * pageSize, pageSize);
        return users;
    }
}

方式二可以使用pageHelper插件

上一篇 下一篇

猜你喜欢

热点阅读