jhipster - issue with custom relationship between two entities - liquibase

I m trying to create a relationship between two entities.
Entity Fournisseur(id,code,libelle)
Entity Catalogue (id, fournisseur_code)
I want the relationship between those two entities be between code and fournisseur_code.
I have modified the liquibase xml generated file for entity catalogue from
<changeSet id="20150116113044" author="jhipster">
<createTable tableName="T_CATALOGUE">
<column name="id" type="bigint" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="fournisseur_id" type="bigint"/>
<column name="produit_id" type="bigint"/>
<column name="marque_id" type="bigint"/>
<column name="pays_id" type="bigint"/>
<column name="emballage_id" type="bigint"/>
</createTable>
<addForeignKeyConstraint baseColumnNames="fournisseur_code"
baseTableName="T_CATALOGUE"
constraintName="fk_catalogue_fournisseur_id"
referencedColumnNames="id"
referencedTableName="T_FOURNISSEUR"/>
to
<changeSet id="20150116113044" author="jhipster">
<createTable tableName="T_CATALOGUE">
<column name="id" type="bigint" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="fournisseur_code" type="varchar(45)"/>
<column name="produit_id" type="bigint"/>
<column name="marque_id" type="bigint"/>
<column name="pays_id" type="bigint"/>
<column name="emballage_id" type="bigint"/>
</createTable>
<addForeignKeyConstraint baseColumnNames="fournisseur_code"
baseTableName="T_CATALOGUE"
constraintName="fk_catalogue_fournisseur_code"
referencedColumnNames="code"
referencedTableName="T_FOURNISSEUR"/>
The table was well generated, but when I m trying to run the getAll function from CatalogueResource, it tells me :
[ERROR] org.hibernate.engine.jdbc.spi.SqlExceptionHelper - Unknown
column 'catalogue0_.fournisseur_id' in 'field list'
I can't figure out why.
If someone knows....
Thank you.

the relation must be connected with the field.
you have to change:
baseColumnNames="fournisseur_code"
to this
baseColumnNames="fournisseur_id"

Related

Liquibase changeset changeLogPropertyDefined is not working

In liquibase I want to execute a particular change set based on the 'context' property value.
In this case I have passed -Dcontext=local (I've checked this values is getting picked properly) through command line and tried to check that property within my changeset by using changeLogPropertyDefined. But It's not working..
Please find below my changeset
<changeSet id="1" author="dm">
<preConditions onFail="MARK_RAN" onSqlOutput="TEST">
<changeLogPropertyDefined property="context" value="local"/>
</preConditions>
<createTable tableName="accountold">
<column autoIncrement="true" name="id" type="BIGINT">
<constraints nullable="false" primaryKey="true"/>
</column>
<column name="version" type="BIGINT">
<constraints nullable="false"/>
</column>
</createTable>
</changeSet>
You should add the "link" to the property in the top of your changeset file to reference value is passed from jvm args:
<property name="context" value="${context}"/>
Then you could use your property in precondition and anywhere you want in this changeset.
P.S. Maybe it's will be better to give different name for jvm arg and lb property to avoid ambiguity of interpretation.

How to migrate join table to entity table with liquibase without liquibase.exception.DatabaseException: ERROR: column "id" contains null values

I'm making the upgrade of the table that previously was just a join table to the real entity. So, it should have no primary key of ids of the entities it joins, and establish its own id. I tried this update configuration:
<changeSet id="20200429180824-1" author="jhipster">
<dropPrimaryKey columnNames="teacher_id, subject_id" tableName="teacher_subject"/>
<addColumn tableName="teacher_subject" author="jhipster">
<column name="id" type="bigint" autoIncrement="${autoIncrement}">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="teacher_status" type="varchar(255)" defaultValue="APPROVED">
<constraints nullable="true" />
</column>
<column name="achieved" type="datetime" defaultValueComputed="CURRENT_TIMESTAMP" >
<constraints nullable="true" />
</column>
<column name="active" type="boolean" defaultValue="true">
<constraints nullable="true" />
</column>
<!-- jhipster-needle-liquibase-add-column - JHipster will add columns here, do not remove-->
</addColumn>
<dropDefaultValue tableName="teacher_subject" columnName="achieved" columnDataType="datetime"/>
</changeSet>
However, at the migration time I'm getting failure with this exception, despite of my expectation that the column should be just created at the moment and pre-populated with autoIncrement data:
liquibase.exception.DatabaseException: ERROR: column "id" contains null values
However, I have realized the root of the problem here is in forcing "nullable=false". After moving it to the different and later execution of the same changeset, the migration succeed. The final changeset looks like, note separate addNotNullConstraint and primaryKey-only <constraints primaryKey="true"/> here:
<changeSet id="20200429180824-1" author="jhipster">
<dropPrimaryKey columnNames="teacher_id, subject_id" tableName="teacher_subject"/>
<addColumn tableName="teacher_subject" author="jhipster">
<column name="id" type="bigint" autoIncrement="true">
<constraints primaryKey="true"/>
</column>
<column name="teacher_status" type="varchar(255)" defaultValue="APPROVED">
<constraints nullable="true" />
</column>
<column name="achieved" type="datetime" defaultValueComputed="CURRENT_TIMESTAMP" >
<constraints nullable="true" />
</column>
<column name="active" type="boolean" defaultValue="true">
<constraints nullable="true" />
</column>
<!-- jhipster-needle-liquibase-add-column - JHipster will add columns here, do not remove-->
</addColumn>
<addNotNullConstraint catalogName="cat"
columnDataType="bigint"
columnName="id"
constraintName="teacher_subject_id_not_null"
tableName="teacher_subject"
validate="true"/>
<dropDefaultValue tableName="teacher_subject" columnName="achieved" columnDataType="datetime"/>
</changeSet>

Liquibase loadData as string, not CLOB resource

The Problem
I recently upgraded Liquibase to 3.6.2 from 3.4.2.
Loading seed data from a CSV into text fields now results in a CLOB resource error. Before it would simply insert the text as a value.
The Setup
I'm using Liquibase to manage migrations of my data.
I have a table with an code and description column. description is of type TEXT.
<changeSet author="" id="create-table-degrees">
<createTable tableName="degrees">
<column name="code"
type="varchar(2)">
<constraints primaryKey="true"/>
</column>
<column name="description"
type="text">
<constraints unique="true"/>
</column>
</createTable>
<rollback>
<dropTable tableName="degrees"/>
</rollback>
</changeSet>
I have seed data in a CSV:
code,description
"D1","MASTERS"
"D2","DOCTORATE"
I load it using loadData:
<changeSet author="" id="seed-degrees">
<loadData file="seeds/degrees.csv"
tableName="degrees" />
</changeSet>
The Error
Unexpected error running Liquibase: CLOB resource not found: MASTERS
The Question
Is there a way to keep Liquibase from interpreting seed values as file paths instead of strings, or do I need to manually define the column types as String in loadData.
e.g. I would like to avoid having to modify the old changeSet to:
<changeSet author="" id="seed-degrees">
<loadData file="seeds/degrees.csv"
tableName="roles">
<column name="description" type="string" />
</loadData>
</changeSet>
The workaround listed in CORE-3287: Anver S December 3, 2018, 3:07 PM
While adding an explicit column type definition as defined in original
stackoverflow post
<column name="description" type="string" />
does the trick - for me it effectively requires to update already
applied changesets which ideally I'd try to avoid.

Liquibase - insert rows with uuid

I have two tables declared as follows:
<changeSet author="istvan" id="country-table-changelog">
<createTable tableName="country">
<column name="id" type="uuid">
<constraints nullable="false" unique="true" />
</column>
<column name="name" type="varchar">
<constraints nullable="false" unique="true" />
</column>
</createTable>
</changeSet>
<changeSet author="istvan" id="region-table-changelog">
<createTable tableName="region">
<column name="id" type="uuid" >
<constraints nullable="false" unique="true" />
</column>
<column name="country_id" type="uuid">
<constraints nullable="false" />
</column>
<column name="name" type="varchar">
<constraints nullable="false" unique="true" />
</column>
</createTable>
</changeSet>
<changeSet author="istvan" id="region-country-foreign-key-constraint">
<addForeignKeyConstraint
baseTableName="region"
baseColumnNames="country_id"
referencedTableName="country"
referencedColumnNames="id"
constraintName="fk_region_country"
onDelete="CASCADE"
onUpdate="RESTRICT"/>
</changeSet>
I want to fill both tables from liquibase changelog file with some values like:
INSERT INTO country VALUES('aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'HUNGARY');
INSERT INTO region VALUES('bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb', 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa', 'Baranya');
In the example I used aaaa's and bbbb's just because of simplicity. I want to generate those UUID's by the DBMS.
What is the best way to do it? Do I have to use SQL in my changelog files or is it possible with XML? I prefer DBMS independent solution like XML or JSON.
My second question is that how can I declare a column with UUID that creates the UUID on insert. Something like:
<column name="id" type="uuid" value="??? GENERATE UUID ???">
<constraints nullable="false" unique="true" />
</column>
Thank you for your time!
You can do this by using properties that are defined depending on the current DBMS.
<property name="uuid_type" value="uuid" dbms="postgresql"/>
<property name="uuid_type" value="uniqueidentifier" dbms="mssql"/>
<property name="uuid_type" value="RAW(16)" dbms="oracle"/>
<property name="uuid_function" value="uid.uuid_generate_v4()" dbms="postgresql"/>
<property name="uuid_function" value="NEWID()" dbms="mssql"/>
<property name="uuid_function" value="sys_guid()" dbms="oracle"/>
Then use those properties when defining the table:
<column name="id" type="${uuid_type}" defaultValueComputed="${uuid_function}">
<constraints nullable="false" unique="true" />
</column>
Note that you need to use defaultValueComputed, not value
If the column is defined with a default value, just leave it out in your insert statements and the database will then generate the UUID when inserting.
For MySQL, put your property just before changeSet tag:
<property name="u_id" value="uuid()" dbms="mysql"/>
then
<column name="ID" type="varchar(255)" valueComputed="${u_id}"/>
NOTE: here valueComputed is used, not defaultValueComputed.
Some databases supports UUID columns: Generate UUID values by default for each row on column of UUID type in H2 Database Engine
I don't think that Liquibase has embedded UUID generator, have a look at defaultValueComputed/valueComputed property for column (http://www.liquibase.org/documentation/column.html) + DB function to generate UUID
Like Rammgarot noted, since we are dealing with columns that need to have unique values, we should use valueComputed instead of defaultValueComputed.
Any of the provided answers didn't help me in case of MySQL, but I was able to work it out using another approach - using triggers.
<changeSet author="nberezovski" id="1">
<createTable tableName="test">
<column name="id" type="varchar(255)">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="description" type="varchar(255)">
...
</createTable>
</changeSet>
<changeSet author="nberezovski" id="2">
<sql splitStatements="false">
CREATE TRIGGER insert_test
BEFORE INSERT ON test
FOR EACH ROW
BEGIN
IF (NEW.id IS NULL) THEN
SET NEW.id = UUID();
END IF;
END;
</sql>
</changeSet>
After that, each manual insert only of values for description MySQL automatically generated an id for me. For example:
insert into test(description) values('some description');
Also that approach helped in loading data using loadData
For SQL SERVER works
<column name="uuid" valueComputed="newid()" />
For me helped this (postgres 14.2):
<property name="uuid_function" value="gen_random_uuid()" dbms="postgresql"/>
<column name="id" valueComputed="${uuid_function}"/>

NHibernate.MappingException occurs when using nullable types

I am using nhibernate to access my database and andromda generates my mapping files.
All is working fine, as long as I am not using nullable datatypes.
What I am trying is to have an entity with a property of type Nullables.NHibernate.NullableInt32Type. My database has the corresponding relation with the column of type "int NULL" (SQL Server).
The corresponding class has the correct data type, too (int?).
But when I try to get values of the database, I get an NHibernate.MappingException:
NHibernate.MappingException : Invalid mapping information specified
for type Namespace.SummaryAttribute, check your mapping file for
property type mismatches
----> System.InvalidCastException : Die angegebene Umwandlung ist ungültig.
<?xml version="1.0" encoding="UTF-8"?>
<hibernate-mapping
xmlns="urn:nhibernate-mapping-2.2"
default-cascade="none">
<class
name="Namespace.SummaryAttribute, Core"
table="SUMMARY_ATTRIBUTE"
dynamic-insert="false"
dynamic-update="false"
lazy="true">
<id name="Id" type="Int64" unsaved-value="0">
<column name="ID" sql-type="NUMERIC(19,0)"/>
<generator class="native">
</generator>
</id>
<property name="ShortName" type="String">
<column name="SHORT_NAME" not-null="true" unique="false" sql-type="VARCHAR(255)"/>
</property>
<property name="LongName" type="String">
<column name="LONG_NAME" not-null="true" unique="false" sql-type="VARCHAR(255)"/>
</property>
<property name="Description" type="String">
<column name="DESCRIPTION" not-null="true" unique="false" sql-type="VARCHAR(255)"/>
</property>
<property name="IsVisible" type="Boolean">
<column name="IS_VISIBLE" not-null="true" unique="false" sql-type="BIT"/>
</property>
<property name="DecimalPlaces" type="Nullables.NHibernate.NullableInt32Type, Nullables.NHibernate">
<column name="DECIMAL_PLACES" not-null="false" unique="false" sql-type="INT"/>
</property>
</class>
</hibernate-mapping>
Without the property "DecimalPlaces" all works fine. Even when I change the property to the simple data type int.
Does anyone have a clue what the problem might be?
Just remove type property from mappings. NHibernate will figure out type by himself, so you should have:
<property name="DecimalPlaces">
<column name="DECIMAL_PLACES" not-null="false" unique="false" sql-type="INT"/>
</property>