(7)FPQuant JHipster

    xiaoxiao2021-03-25  93

    本文是对JHipster开发文档的部分翻译,供个人学习之用。

    原文链接:https://jhipster.github.io/creating-an-entity/

    1.介绍

    一旦你创建了应用,就会希望创建实体。

    对于每个实体,你需要:

    一个数据库表一个Liquibase变化集合一个JPA实体一个Spring Data JPA Repository一个Spring MVC REST Controller,有基本的CRUD操作一个Angular router,一个component和一个service一个HTML页面集成的测试,来验证所有都像预计的一样运行性能测试,观察是否所有都顺利运行

    如果已经有几个类,你可能想要他们彼此之间有关系,这就需要:

    一个数据库的外键特定的JavaScript和HTML代码来管理各种关系

    实体生成器将会生成必要的文件,并且为每个实体提供一个CRUD的前后端。生成器可以用yo jhipster:entity <entityName> --[options]来调用,可选参数可以用yo jhipster:entity --help来查询,下面是一些选项:

    --table-name <table-name>:默认情况下JHipster会生成一个名为实体名字的表,如果你想要一个不一样的表名,可以在这里传递参数。--angular-suffix <suffix>:如果你想要所有的Angular路由都有一个自定义的后缀,可以在这里传递参数。--regenerate:这会重新生成一个已存在的实体。--skip-server:这会跳过服务器端的代码,只生成客户端的代码。--skip-client:这会跳过客户端的代码,只生成服务器端的代码。

    2.JHipster UML和JDL Studio

    如果想要创建许多实体,可以使用图形工具

    JHipster UML,让你可以使用一个UML编辑器JDL Studio,使用JDL创建实体和关系的线上工具

    如果使用JDL Studio

    执行yo jhipster:import-jdl your-jdl-file.jh,用import-jdl生成器从一个JDL文件生成实体运行npm install -g jhipster-uml,然后jhipster-uml yourFileName.jh,用JHipster UML来代替import-jdl生成器

    3.实体域

    可以对每种实体添加想要的域,只需要输入域的名字和他们的类型,JHipster就会生成从Angular HTML页面到Liquibase changelog所有需要的代码和配置。

    这些域不能包含所用技术的保留关键字,如MySQL和Java的关键字。

    4.域类型

    JHipster支持许多域类型,这种支持依赖于你的数据库端,我们只要使用Java类型来描述即可。

    String:Java字符串,默认大小取决于后端如JPA就是255,可以使用验证规则来修改Integer:整型数Long:长整型Float:浮点数Double:双精度浮点数BigDecimal:java.math.BigDecimal对象,用于精确的数学计算LocalDate:java.time.LocalDate对象,用于准确管理日期ZoneDateTime:java.time.ZonedDateTime对象,用于准确管理日期和时间Boolean:布尔值Enumeration:java枚举类型,选择后,生成器会问你想要枚举类型中的什么值,并且会创建一个特殊的enum类来存储Blob:Blob对象,用于存储一些二进制数据,选择后,生成器会问你是否想要存储一般的二进制数据,一个图像对象或一个CLOB(长文本)。图像将可以在Angular端特殊处理,他们将会显示在用户终端。

    5.验证

    每个域都可以进行验证,不同的域类型可以有不同的验证选项。

    验证会自动生成:

    HTML页面,使用AngularJS验证机制Java领域对象,使用Bean验证

    当领域对象用于以下场景时,将自动进行Bean验证:

    Spring MVC REST控制器(使用@Valid注解)Hibernate/JPA(实体在保存前自动验证)

    验证信息也会用于生成更精确数据库列元数据:

    Required域将标志为non-nullable有最大长度的域将有相同的列长度

    验证有一些限制:

    不支持所有的AngularJS和Bean验证选项,只有两个API都有的。正则表达式在JavaScript和Java中不一样,所以设置一个后可能需要稍稍调整另一个生成的模式JHipster生成一般实体的单元测试,却不知道你的验证规则,你需要更新单元测试中用到的示例值,这样他们才会传递验证规则

    6.实体关系

    实体关系只有当存在JPA时对SQL数据库有用,如果选择了Cassandra或MongoDB,就没有用。

    关系可以存在于两个实体之间,JHipster将会生成下列代码:

    在生成的实体中用JPA管理关系

    对存在于数据库中的关系创建正确的Liquibase changelog

    生成AngularJS前端,你可以在图像用户界面进行管理

    双向的一对多关系:

    Owner(1) <-----> (*)Car,一个主人可以有多辆车,一辆车只能有一个主人,并且通过车可以找到主人,通过主人可以找到所有的车。

    先创建Owner:

    Generating relationships with other entities ? Do you want to add a relationship to another entity? Yes ? What is the name of the other entity? Car ? What is the name of the relationship? car ? What is the type of the relationship? one-to-many ? What is the name of this relationship in the other entity? owner再生成Car:

    Generating relationships with other entities ? Do you want to add a relationship to another entity? Yes ? What is the name of the other entity? Owner ? What is the name of the relationship? owner ? What is the type of the relationship? many-to-one ? When you display this relationship with AngularJS, which field from 'Owner' do you want to use? id同样在JDL中可以:

    entity Owner entity Car relationship OneToMany { Owner{car} to Car{owner} }这样在AngularJS客户界面上当选择Owner时就有一个下拉的Car

    单向的多对一关系:

    Owner(1) <------- (*)Car,一个主人可以有多辆车,一辆车只能有一个主人,但是通过主人不能找到车,通过车可以找到他的主人。

    先生成Owner

    Generating relationships with other entities ? Do you want to add a relationship to another entity? No

    再生成Car

    Generating relationships with other entities ? Do you want to add a relationship to another entity? Yes ? What is the name of the other entity? Owner ? What is the name of the relationship? owner ? What is the type of the relationship? many-to-one ? When you display this relationship with AngularJS, which field from 'Owner' do you want to use? id

    JDL:

    entity Owner entity Car relationship ManyToOne { Car{owner} to Owner }这样就不能从Owner实体中添加或移除车。

    单向的一对多关系:

    Owner (1) ------> (*) Car,一个主人可以有多辆车,一辆车只能有一个主人,但是通过主人可以找到所有的车,通过车不能找到它的主人。

    这种关系在JHipster中还不默认提供,有两种解决方法:

    执行一个双向映射,不做修改地使用执行一个双向映射,将其修改为一个单向映射:

    移除@OneToMany注解的mappedBy属性生成必要的连接表:mvn liquibase:diff来生成

    JDL不支持。

    两对相同实体上的两个一对多关系:

    Person (1) <---owns-----> (*) Car

    Person (1) <---drives----> (*) Car

    先生成Person实体:

    Generating relationships with other entities ? Do you want to add a relationship to another entity? Yes ? What is the name of the other entity? Car ? What is the name of the relationship? ownedCar ? What is the type of the relationship? one-to-many ? What is the name of this relationship in the other entity? owner ... Generating relationships with other entities ? Do you want to add a relationship to another entity? Yes ? What is the name of the other entity? Car ? What is the name of the relationship? drivedCar ? What is the type of the relationship? one-to-many ? What is the name of this relationship in the other entity? driver再生成Car实体,使用在Person中配置的关系名称:

    Generating relationships with other entities ? Do you want to add a relationship to another entity? Yes ? What is the name of the other entity? Person ? What is the name of the relationship? owner ? What is the type of the relationship? many-to-one ? When you display this relationship with AngularJS, which field from 'Person' do you want to use? id ... Generating relationships with other entities ? Do you want to add a relationship to another entity? Yes ? What is the name of the other entity? Person ? What is the name of the relationship? driver ? What is the type of the relationship? many-to-one ? When you display this relationship with AngularJS, which field from 'Person' do you want to use? idJDL:

    entity Person entity Car relationship OneToMany { Person{ownedCar} to Car{owner} } relationship OneToMany { Person{drivedCar} to Car{driver} }在客户端你可以在选择Person的owner和driver域时有Car的下拉列表

    多对多关系:

    Driver (*) <--------> (*) Car,一个司机可以开多辆车,一辆车可以有多个司机。

    在数据库层,意味着在Driver和Car之间有一个连接表。

    对于JPA,两个实体中的一个需要管理这个关系,我们这里让Car来管理,负责添加或删除Driver。

    先生成Driver:

    Generating relationships with other entities ? Do you want to add a relationship to another entity? Yes ? What is the name of the other entity? Car ? What is the name of the relationship? car ? What is the type of the relationship? many-to-many ? Is this entity the owner of the relationship? No ? What is the name of this relationship in the other entity? driver再生成Car,是关系的所有者:

    Generating relationships with other entities ? Do you want to add a relationship to another entity? Yes ? What is the name of the other entity? Driver ? What is the name of the relationship? driver ? What is the type of the relationship? many-to-many ? Is this entity the owner of the relationship? Yes ? When you display this relationship with AngularJS, which field from 'Driver' do you want to use? id JDL:

    entity Driver entity Car relationship ManyToMany { Car{driver} to Driver{car} }在客户端,因为Car是所有者,可以在Car中下拉选择Driver。

    一对一关系:

    Driver (1) <---------->(1) Car,一辆车只有一个司机,一个司机只开一辆车。

    先生成Driver

    Generating relationships with other entities ? Do you want to add a relationship to another entity? Yes ? What is the name of the other entity? Car ? What is the name of the relationship? car ? What is the type of the relationship? one-to-one ? Is this entity the owner of the relationship? No ? What is the name of this relationship in the other entity? driver再生成Car

    Generating relationships with other entities ? Do you want to add a relationship to another entity? Yes ? What is the name of the other entity? Driver ? What is the name of the relationship? driver ? What is the type of the relationship? one-to-one ? Is this entity the owner of the relationship? Yes ? What is the name of this relationship in the other entity? car ? When you display this relationship with AngularJS, which field from 'Driver' do you want to use? idJDL: entity Driver entity Car relationship OneToOne { Car{driver} to Driver{car} }因为Car是关系的所有者,可以在Car中下拉选择Driver。

    单向的一对一关系:

    Citizen(1) <--------->(1)Passport,一个公民只能有一张护照,但是一个护照实例不能有主人。

    先生成Passport:

    Generating relationships with other entities ? Do you want to add a relationship to another entity? No再生成Citizen:

    Generating relationships with other entities ? Do you want to add a relationship to another entity? Yes ? What is the name of the other entity? Passport ? What is the name of the relationship? passport ? What is the type of the relationship? one-to-one ? Is this entity the owner of the relationship? Yes ? What is the name of this relationship in the other entity? citizen ? When you display this relationship with AngularJS, which field from 'Passport' do you want to use? idJDL:

    entity Citizen entity Passport relationship OneToOne { Citizen{passport} to Passport }一个公民持有一个护照,但是护照中没有定义公民实例,在客户端,Citizen中可以下拉选择Passport。

    7.数据传输类型

    默认的JHipster实体不使用DTOs,但是他们是可选的

    默认情况下,JHipster直接在REST终端使用领域对象——JPA实体,主要的好处就是让代码更易用、易理解、易扩展。

    然而,对于复杂的用例,可能想用可以被REST终端暴露的数据转化对象(DTO)。这些对象在领域对象的顶层添加了一个额外的层,专门用于REST层。主要的好处就是可以集合多个领域对象。

    DTO的使用原理:

    当生成一个JHipster实体时,可以选择是否也生成DTO,如果选择:

    生成一个DTO,映射到依赖的实体集合多对一的关系,只使用ID和用于展示的域。例如一个User实体的多对一关系会将userId域和userLogin域添加到DTO中。将忽略非所有者上的一对多、多对多关系,这符合实体的运作方式(他们对这些域使用@JsonIgnore注解)对于所有者的多对多关系,使用其他实体的DTO并将他们放在一个Set中使用,因此,只有当其他实体也使用DTO时才能支持。

    使用MapStruct映射DTO和实体:

    DTO看起来很像实体,经常需要将他们想办法相互映射。

    JHipster选择的方式是使用MapStruct,这是一个注解处理器,作为Java编译器的插件,将自动生成必要的映射。

    这简介又有效,并且似乎不使用反射(当在mapper中用到很多时,性能很受影响)

    为MapStruct配置IDE:

    MapStruct需要设置为在IDE编译项目时自动运行

    如果使用Maven,需要激活IDE的maven配置。

    MapStruct的进一步用法:

    MapStruct的mapper被配置为Spring Beans,并且支持独立注入。

    建议将一个Repository注入一个mapper,这样就可以从mapper通过它的ID获取一个可控的JPA实体。

    示例:

    @Mapper public abstract class CarMapper { @Inject private UserRepository userRepository; @Mapping(source = "user.id", target = "userId") @Mapping(source = "user.login", target = "userLogin") public abstract CarDTO carToCarDTO(Car car); @Mapping(source = "userId", target = "user") public abstract Car carDTOToCar(CarDTO carDTO); public User userFromId(Long id) { if (id == null) { return null; } return userRepository.findOne(id); } }

    8.分页

    目前如果使用Cassandra来创建应用是不能进行分页的。

    分页使用了和GitHub API中一样的Linker header。JHipster提供对服务器和客户端特定的自定义实现。

    生成实体时,JHipster提供4中分页选项:

    不分页简单分页,基于Bootstrap pager完全分页系统,基于Bootstrap分页组件有限滚动系统,基于有限滚动指令

    9.更新已存在的实体

    实体的配置保存在特定的.jhipster目录下的.json文件中。如果你再运行一次实体生成器,使用已存在的实体名称,你可以更新或重新生成这个实体。

    此时有四种选项:

    重新生成实体(可以在运行生成器时传递一个--regenerate标志来强制执行)添加域和关系去除域和关系退出

    你可能因为下列原因想要更新实体:

    对已存在的实体添加/移除域和关系重新设置实体的代码到原始状态更新了JHipster,想要用新的模板来生成实体更改了.json配置文件,有一个实体的新的版本复制粘贴了.json文件,想要一个新的与拷贝实体很接近的实体

    为了立即重新生成实体,可以使用下面的命令,如果更改了文件询问问题时,可以将--force去除

    Linux/Mac:for f in `ls .jhipster`;do yo jhipster:entity ${f%.*} --force; done

    Windows:for %f in (.jhipster/*) do yo jhipster:entity %~nf --force

    转载请注明原文地址: https://ju.6miu.com/read-20394.html

    最新回复(0)