jhipster / generator-jhipster

JHipster is a development platform to quickly generate, develop, & deploy modern web applications & microservice architectures.
https://www.jhipster.tech
Apache License 2.0
21.44k stars 4.02k forks source link

[Oracle] Table name not used for constraint names nor join tables #8609

Closed rubensa closed 5 years ago

rubensa commented 5 years ago
Overview of the issue

When you specify a table name for an entity, that table name should be used to generate restrictions (foreign keys, for example) and join tables (if they are needed).

Motivation for or Use Case

I'm using Oracle as production database. I know there are length restrictions in the table, restrictions... that Oracle can handle. I know that I can specify the table name for my Entities so I use that to short my table names.

The problem is that I can't specify the names for the generated restrictions and those are based on Entity names (and ignore the specified table names). This cause collisions in fk names cause truncated names for Oracle (if the name of the entities has similar stating name).

Reproduce the error

Generate application from this Model.jdl

application {
  config {
    applicationType monolith
    authenticationType jwt
    baseName demo
    buildTool maven
    cacheProvider hazelcast
    clientFramework angularX
    clientPackageManager npm
    databaseType sql
    devDatabaseType h2Disk
    enableHibernateCache true
    enableSwaggerCodegen false
    enableTranslation true
    jhiPrefix auto
    languages [en]
    messageBroker false
    nativeLanguage en
    packageName com.company.demo
    prodDatabaseType oracle
    searchEngine false
    serverPort 8080
    serviceDiscoveryType no
    skipClient false
    skipServer false
    skipUserManagement false
    testFrameworks []
    useSass false
    websocket false
  }
  entities *
}

entity MyLongNamedEntityOne (mlneo) {
    field1 String maxlength(4000),
    field2 Integer required
}

entity MyLongNamedEntityTwo (mlnet) {
    field1 String maxlength(4000),
    field2 Integer required
}

entity MyLongNamedAgregatedEntity (mlnae) {

}

relationship ManyToOne {
    MyLongNamedAgregatedEntity {myLongNamedEntityOne required} to MyLongNamedEntityOne,
    MyLongNamedAgregatedEntity {myLongNamedEntityTwo} to MyLongNamedEntityTwo
}

You get the following warnigs in generator:

WARNING! The generated constraint name "fk_my_long_named_agregated_entity_my_long_named_entity_one" is too long for Oracle (which has a 30 characters limit). It will be truncated!
WARNING! The generated constraint name "fk_my_long_named_agregated_entity_my_long_named_entity_two" is too long for Oracle (which has a 30 characters limit). It will be truncated!
WARNING! The generated join table "my_long_named_agregated_entity_my_long_named_entity_one" is too long for Oracle (which has a 30 characters limit). It will be truncated!
WARNING! The generated join table "my_long_named_agregated_entity_my_long_named_entity_two" is too long for Oracle (which has a 30 characters limit). It will be truncated!

Question: Why the warning about join table names, as those are not going to be generated (cause not needed)?

If you review the generated liquibase changelog file for MyLongNamedAgregatedEntity:

<?xml version="1.0" encoding="utf-8"?>
<databaseChangeLog
    xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd">
    <!--
        Added the constraints for entity MyLongNamedAgregatedEntity.
    -->
    <changeSet id="20181019081551-2" author="jhipster">

        <addForeignKeyConstraint baseColumnNames="my_long_named_entity_one_id"
                                 baseTableName="mlnae"
                                 constraintName="my_long_named__my_long_name_id"
                                 referencedColumnNames="id"
                                 referencedTableName="mlneo"/>

        <addForeignKeyConstraint baseColumnNames="my_long_named_entity_two_id"
                                 baseTableName="mlnae"
                                 constraintName="my_long_named__my_long_name_id"
                                 referencedColumnNames="id"
                                 referencedTableName="mlnet"/>

    </changeSet>
</databaseChangeLog>

You can see that there is a constraint name collision my_long_named__my_long_name_id.

Related issues

6006

3723

3839

3881

Suggest a Fix

I you specify a table name that should be used to generate the constraint name. It should be great If you could specify the restriction name (similar to specify the table name). For example, something like this:

relationship ManyToOne {
    MyLongNamedAgregatedEntity {myLongNamedEntityOne required} to MyLongNamedEntityOne (fk_mlnae_mlneo_id),
    MyLongNamedAgregatedEntity {myLongNamedEntityTwo} to MyLongNamedEntityTwo (fk_mlnae_mlnet_id)
}
JHipster Version(s)

5.5.0

JHipster configuration

Using JHipster version installed globally Executing jhipster:info Options: from-cli: true Welcome to the JHipster Information Sub-Generator

JHipster Version(s)
demo@0.0.0 /media/data/rubensa/development/vscode/workspace/autotriaje/pruebas
└── generator-jhipster@5.5.0
JHipster configuration, a .yo-rc.json file generated in the root folder
.yo-rc.json file
{
  "generator-jhipster": {
    "clientPackageManager": "npm",
    "databaseType": "sql",
    "devDatabaseType": "h2Disk",
    "enableHibernateCache": true,
    "enableSwaggerCodegen": false,
    "enableTranslation": true,
    "jhiPrefix": "auto",
    "languages": [
      "en"
    ],
    "messageBroker": false,
    "nativeLanguage": "en",
    "packageName": "com.company.demo",
    "packageFolder": "com/company/demo",
    "prodDatabaseType": "oracle",
    "searchEngine": false,
    "serviceDiscoveryType": false,
    "skipClient": false,
    "skipServer": false,
    "testFrameworks": [],
    "websocket": false,
    "applicationType": "monolith",
    "authenticationType": "jwt",
    "baseName": "demo",
    "buildTool": "maven",
    "cacheProvider": "hazelcast",
    "clientFramework": "angularX",
    "serverPort": "8080",
    "skipUserManagement": false,
    "useSass": false,
    "jhipsterVersion": "5.5.0",
    "jwtSecretKey": ""
  },
  "entities": [
    "MyLongNamedEntityOne",
    "MyLongNamedEntityTwo",
    "MyLongNamedAgregatedEntity"
  ]
}
JDL for the Entity configuration(s) entityName.json files generated in the .jhipster directory
JDL entity definitions
entity MyLongNamedEntityOne (mlneo) {
  field1 String maxlength(4000),
  field2 Integer required
}
entity MyLongNamedEntityTwo (mlnet) {
  field1 String maxlength(4000),
  field2 Integer required
}
entity MyLongNamedAgregatedEntity (mlnae)
relationship ManyToOne {
  MyLongNamedAgregatedEntity{myLongNamedEntityOne required} to MyLongNamedEntityOne,
  MyLongNamedAgregatedEntity{myLongNamedEntityTwo} to MyLongNamedEntityTwo
}

Environment and Tools

java version "1.8.0_181" Java(TM) SE Runtime Environment (build 1.8.0_181-b13) Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)

git version 2.17.1

node: v8.11.3

npm: 5.6.0

Docker version 18.06.1-ce, build e68fc7a

docker-compose version 1.21.2, build a133471

Congratulations, JHipster execution is complete!

Entity configuration(s) entityName.json files generated in the .jhipster directory

MyLongNamedAgregatedEntity.json

{
    "name": "MyLongNamedAgregatedEntity",
    "fields": [],
    "relationships": [
        {
            "relationshipType": "many-to-one",
            "relationshipValidateRules": "required",
            "relationshipName": "myLongNamedEntityOne",
            "otherEntityName": "myLongNamedEntityOne",
            "otherEntityField": "id"
        },
        {
            "relationshipType": "many-to-one",
            "relationshipName": "myLongNamedEntityTwo",
            "otherEntityName": "myLongNamedEntityTwo",
            "otherEntityField": "id"
        }
    ],
    "changelogDate": "20181019081551",
    "entityTableName": "mlnae",
    "dto": "no",
    "pagination": "no",
    "service": "no",
    "jpaMetamodelFiltering": false,
    "fluentMethods": true,
    "clientRootFolder": "",
    "applications": [
        "demo"
    ]
}

MyLongNamedEntityOne.json

{
    "name": "MyLongNamedEntityOne",
    "fields": [
        {
            "fieldName": "field1",
            "fieldType": "String",
            "fieldValidateRules": [
                "maxlength"
            ],
            "fieldValidateRulesMaxlength": 4000
        },
        {
            "fieldName": "field2",
            "fieldType": "Integer",
            "fieldValidateRules": [
                "required"
            ]
        }
    ],
    "relationships": [],
    "changelogDate": "20181019081549",
    "entityTableName": "mlneo",
    "dto": "no",
    "pagination": "no",
    "service": "no",
    "jpaMetamodelFiltering": false,
    "fluentMethods": true,
    "clientRootFolder": "",
    "applications": [
        "demo"
    ]
}

MyLongNamedEntityTwo.json

{
    "name": "MyLongNamedEntityTwo",
    "fields": [
        {
            "fieldName": "field1",
            "fieldType": "String",
            "fieldValidateRules": [
                "maxlength"
            ],
            "fieldValidateRulesMaxlength": 4000
        },
        {
            "fieldName": "field2",
            "fieldType": "Integer",
            "fieldValidateRules": [
                "required"
            ]
        }
    ],
    "relationships": [],
    "changelogDate": "20181019081550",
    "entityTableName": "mlnet",
    "dto": "no",
    "pagination": "no",
    "service": "no",
    "jpaMetamodelFiltering": false,
    "fluentMethods": true,
    "clientRootFolder": "",
    "applications": [
        "demo"
    ]
}
Browsers and Operating System

Linux 4.15.0-36-generic Ubuntu SMP Mon Sep 24 16:19:09 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

jdubois commented 5 years ago

We used to handle that, but I remember we removed it when Oracle accepted to have bigger names... Which Oracle version are you using?

rubensa commented 5 years ago

I'm using Oracle 12c but, as far a I know, I can't tell jhipster-generator to not apply restrictions in generated names length if the database is Oracle (I can't tell the version, isn't it?).

So jhipster, if you specify Oracle as production database, always truncate the names (and don't use the specified table names -I think that database is irrelevant for this-, It uses the table name derived from entity name NOTE: I mean for constraints an not specified join tables ).

According to Doc that is the min Oracle version supported by jhipster-generator.

rubensa commented 5 years ago

As a general rule It should generate something like this:

<?xml version="1.0" encoding="utf-8"?>
<databaseChangeLog
    xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.5.xsd">
    <!--
        Added the constraints for entity MyLongNamedAgregatedEntity.
    -->
    <changeSet id="20181019081551-2" author="jhipster">

        <addForeignKeyConstraint baseColumnNames="my_long_named_entity_one_id"
                                 baseTableName="mlnae"
                                 constraintName="fk_mlnae_mlneo"
                                 referencedColumnNames="id"
                                 referencedTableName="mlneo"/>

        <addForeignKeyConstraint baseColumnNames="my_long_named_entity_two_id"
                                 baseTableName="mlnae"
                                 constraintName="fk_mlnae_mlnet"
                                 referencedColumnNames="id"
                                 referencedTableName="mlnet"/>

    </changeSet>
</databaseChangeLog>

been constraintName = "fk" + baseTableName + "" + referencedTableName.

And I would add support to specify the constraint name (to allow avoid collision if two relations from one Entity to Other, for example from Car to Driver if you have pilot and copilot attributes).

deepu105 commented 5 years ago

There is a flag to disable long name checks, try running jhipster entity --help

But in either case the custom table names should be used here so i'm marking it as a bug

rubensa commented 5 years ago

@deepu105 What's supposed to be the flag?

If I run jhipster entity --help (JHipster v5.6.0) I get:

> jhipster entity --help
Using JHipster version installed globally

  Usage: entity [options] [name]

  Create a new JHipster entity: JPA entity, Spring server-side components and Angular client-side components

  Options:

    -h, --help  output usage information
Usage:
  yo jhipster:entity <name> [options]

Options:
  -h,   --help                # Print the generator's options and usage
        --skip-cache          # Do not remember prompt answers                                                                                                    Default: false
        --skip-install        # Do not automatically install dependencies                                                                                         Default: false
        --from-cli            # Indicates the command is run from JHipster CLI                                                                                    Default: false
        --regenerate          # Regenerate the entity without presenting an option to update it                                                                   Default: false
        --table-name          # Specify table name that will be used by the entity
        --fluent-methods      # Generate fluent methods in entity beans to allow chained object construction                                                      Default: true
        --angular-suffix      # Use a suffix to generate Angular routes and files, to avoid name clashes
        --client-root-folder  # Use a root folder name for entities on client side. By default its empty for monoliths and name of the microservice for gateways
        --skip-ui-grouping    # Disables the UI grouping behaviour for entity client side code                                                                    Default: false
        --skip-server         # Skip the server-side code generation                                                                                              Default: false
        --skip-client         # Skip the client-side code generation                                                                                              Default: false
        --db                  # Provide DB option for the application when using skip-server flag
        --experimental        # Enable experimental features. Please note that these features may be unstable and may undergo breaking changes at any time        Default: false

Arguments:
  name  # Entity name  Type: String  Required: true

Description:
    Creates a new JHipster entity: JPA entity, Spring server side components and client side components

Example:
    jhipster entity Foo

    This will create:
        .jhipster/Foo.json
        src/main/java/package/domain/Foo.java
        src/main/java/package/repository/FooRepository.java
        src/main/java/package/web/rest/FooResource.java
        src/main/resources/config/liquibase/changelog/20150128232313_added_entity_Foo.xml
        src/main/webapp/app/entities/foo/foos.html
        src/main/webapp/app/entities/foo/foo-detail.html
        src/main/webapp/app/entities/foo/foo.js
        src/main/webapp/app/entities/foo/foo.controller.js
        src/main/webapp/app/entities/foo/foo-detail.controller.js
        src/main/webapp/app/entities/foo/foo.service.js
        src/test/java/package/web/rest/FooResourceTest.java
        src/main/webapp/i18n/en/foo.json
        src/main/webapp/i18n/fr/foo.json

No mention to any option for disabling long name checks.

deepu105 commented 5 years ago

Seems like the flag is at the app level skip-check-length-of-identifier

Thanks & Regards, Deepu

On Mon, Nov 5, 2018 at 11:53 AM rubensa notifications@github.com wrote:

@deepu105 https://github.com/deepu105 What's supposed to be the flag?

If I run jhipster entity --help (JHipster v5.6.0) I get:

jhipster entity --help Using JHipster version installed globally

Usage: entity [options] [name]

Create a new JHipster entity: JPA entity, Spring server-side components and Angular client-side components

Options:

-h, --help  output usage information

Usage: yo jhipster:entity [options]

Options: -h, --help # Print the generator's options and usage --skip-cache # Do not remember prompt answers Default: false --skip-install # Do not automatically install dependencies Default: false --from-cli # Indicates the command is run from JHipster CLI Default: false --regenerate # Regenerate the entity without presenting an option to update it Default: false --table-name # Specify table name that will be used by the entity --fluent-methods # Generate fluent methods in entity beans to allow chained object construction Default: true --angular-suffix # Use a suffix to generate Angular routes and files, to avoid name clashes --client-root-folder # Use a root folder name for entities on client side. By default its empty for monoliths and name of the microservice for gateways --skip-ui-grouping # Disables the UI grouping behaviour for entity client side code Default: false --skip-server # Skip the server-side code generation Default: false --skip-client # Skip the client-side code generation Default: false --db # Provide DB option for the application when using skip-server flag --experimental # Enable experimental features. Please note that these features may be unstable and may undergo breaking changes at any time Default: false

Arguments: name # Entity name Type: String Required: true

Description: Creates a new JHipster entity: JPA entity, Spring server side components and client side components

Example: jhipster entity Foo

This will create:
    .jhipster/Foo.json
    src/main/java/package/domain/Foo.java
    src/main/java/package/repository/FooRepository.java
    src/main/java/package/web/rest/FooResource.java
    src/main/resources/config/liquibase/changelog/20150128232313_added_entity_Foo.xml
    src/main/webapp/app/entities/foo/foos.html
    src/main/webapp/app/entities/foo/foo-detail.html
    src/main/webapp/app/entities/foo/foo.js
    src/main/webapp/app/entities/foo/foo.controller.js
    src/main/webapp/app/entities/foo/foo-detail.controller.js
    src/main/webapp/app/entities/foo/foo.service.js
    src/test/java/package/web/rest/FooResourceTest.java
    src/main/webapp/i18n/en/foo.json
    src/main/webapp/i18n/fr/foo.json

No mention to any option for disabling long name checks.

β€” You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/jhipster/generator-jhipster/issues/8609#issuecomment-435833544, or mute the thread https://github.com/notifications/unsubscribe-auth/ABDlF65MdlYrmhTswWhWVdtJS_iKEEixks5usBjAgaJpZM4Xv7Ka .

jdubois commented 5 years ago

Closing as the PR is merged!