How to handle special custom foregin key requirement in moqui entity definitions - moqui

I have two entities defined as below:
<entity entity-name="e1" package-name="p">
<field name="f1" type="id" is-pk="true"/>
<field name="f2" type="id" is-pk="true"/>
<field name="f3" type="text-medium" />
<entity/>
<entity entity-name="e2" package-name="p">
<field name="f4" type="id" is-pk="true"/>
<field name="f5" type="id" is-pk="true"/>
<field name="f6" type="text-medium"/>
<entity/>
As seen in above definition, there are two(composite) primary-keys in both tables. Adding following relation
relationship type="one" related-entity-name="e2"
to e1 creates a relation with both the primary keys in other table. I don't want that. How do I create a foreign key realtionship so that:
e1.f2 (single column) referes to only single column of the other table e2.f5 ?
Please help.

What you are describing is a type "many" relationship, not a type "one" which would have a foreign key. This is a database constraint, not a Moqui one, but a foreign key must refer to the entire primary key of the related table.

Related

Liquibase check constraint between two tables

I want to create two new columns each one of them is in a different table.
For example: on company table i want to create a column with name last_registration_number and the second column called registration_number on employee table with check constraint that follows this logic
registration_number of employee table <= last_registration_number of company table
I couldn't found how to do this between two tables.
What is the proper way to do this?
I suppose Liquibase PRO version could help. It has addCheckConstraint tag (as well as edit and drop). Here's a link to the description.
Also there's a checkConstraint attribute in constraints tag:
<createTable tableName="foo">
<column name="bar" type"integer">
<constraints checkConstraint="your condition here"/>
</column>
</createTable>
but I'm not sure if it'll work, since the pull request basics of implementing checkConstraint is still open.
Or if you can just play around with sql tag which allows you to do anything you want in plain SQL.

With Liquibase, is there a difference between using a unique <createIndex> and using <column> with a unique constraint?

Liquibase has two ways to define a column as unique:
When creating the table, using <constraints> on the column:
<createTable tableName="my_table">
<column name="my_column">
<constraints unique="true"
uniqueConstraintName="my_table_my_column_uk">
</column>
</createTable>
After creating the table, using <createIndex>:
<createTable tableName="my_table">
<column name="my_column"/>
</createTable>
<createIndex tableName="my_table" unique="true"
indexName="my_table_my_column_uk">
<column name="my_column"/>
</createIndex>
Is there any difference between these two approaches for single-column unique keys?
In my own observations with MySQL, there seems to be no difference. Both declarations (above) yield the same SHOW CREATE TABLE result:
...
UNIQUE_KEY `my_table_my_column_uk` (`my_column`)
...
However, does this hold true for all database implementations, or does <createIndex unique="true"> generate different schema output from <constraint unique="true"/> for different databases?
Background: I have a script that has built the liquibase changelog directly from my relational model in the code. The generation script created BOTH declarations if the model indicated the column was unique. I'm cleaning up the generated results and would like to remove one of the declarations, and want to know if that's appropriate.
See PostgreSQL Documentation:
Note: The preferred way to add a
unique constraint to a table is ALTER
TABLE ... ADD CONSTRAINT. The use of
indexes to enforce unique constraints
could be considered an implementation
detail that should not be accessed
directly. One should, however, be
aware that there's no need to manually
create indexes on unique columns;
doing so would just duplicate the
automatically-created index.
So a unique constraint is a concept which is implemented (in PostgreSQL) with a unique index.
I guess it depends on the target DBMS.
In PostgreSQL, Oracle and DB2 there is a differences between a unique index and an unique constraint.
The unique constraint can be the target of a foreign key constraint but the unique index cannot. Don't know if that is the same with MySQL.

joining two tables with differnt join column names

I have two tables A -> B with many-to-one mapping/associations.
Table B's primary key is foreign key in table A.
The problem is column names in both tables are different. let's say B has primary key column "typeNumId" which is foreign key in table A as "type". How can I join both tables on this column? how can I specify mapping to indicate that tables have to join on "typeNumId" and "type" which is essentially same.
especially is this possible through hibernate config ( hbm files) ?
something like
<many-to-one name="Type" class="com.domain.ProcedureType" update="false" insert="false" fetch="join" lazy="false">
<column name="? <this is in questions? >" not-null="true" />
</many-to-one>
The ON clause:
select * from A join B on A.type = B.typeNumId
You declare the name of the foreign key using the column attribute of the many-to-one element or the equivalnent nested column element. From the documentation:
5.1.12. Many-to-one
An ordinary association to another
persistent class is declared using a
many-to-one element. The relational
model is a many-to-one association; a
foreign key in one table is
referencing the primary key column(s)
of the target table.
<many-to-one
name="propertyName" (1)
column="column_name" (2)
class="ClassName" (3)
cascade="cascade_style" (4)
fetch="join|select" (5)
update="true|false" (6)
insert="true|false" (6)
property-ref="propertyNameFromAssociatedClass" (7)
access="field|property|ClassName" (8)
unique="true|false" (9)
not-null="true|false" (10)
optimistic-lock="true|false" (11)
lazy="proxy|no-proxy|false" (12)
not-found="ignore|exception" (13)
entity-name="EntityName" (14)
formula="arbitrary SQL expression" (15)
node="element-name|#attribute-name|element/#attribute|."
embed-xml="true|false"
index="index_name"
unique_key="unique_key_id"
foreign-key="foreign_key_name"
/>
name: the name of the property.
column (optional): the name of the foreign key column. This can also be
specified by nested
element(s).
class (optional - defaults to the property type determined by
reflection): the name of the
associated class.
cascade (optional): specifies which operations should be cascaded from the
parent object to the associated
object.
fetch (optional - defaults to select): chooses between outer-join
fetching or sequential select
fetching.
update, insert (optional - defaults to true): specifies that the mapped
columns should be included in SQL
UPDATE and/or INSERT statements.
Setting both to false allows a pure
"derived" association whose value is
initialized from another property that
maps to the same column(s), or by a
trigger or other application.
property-ref (optional): the name of a property of the associated class
that is joined to this foreign key. If
not specified, the primary key of the
associated class is used.
access (optional - defaults to property): the strategy Hibernate uses
for accessing the property value.
unique (optional): enables the DDL generation of a unique constraint for
the foreign-key column. By allowing
this to be the target of a
property-ref, you can make the
association multiplicity one-to-one.
not-null (optional): enables the DDL generation of a nullability
constraint for the foreign key
columns.
optimistic-lock (optional - defaults to true): specifies that
updates to this property do or do not
require acquisition of the optimistic
lock. In other words, it determines if
a version increment should occur when
this property is dirty.
lazy (optional - defaults to proxy): by default, single point
associations are proxied.
lazy="no-proxy" specifies that the
property should be fetched lazily when
the instance variable is first
accessed. This requires build-time
bytecode instrumentation. lazy="false"
specifies that the association will
always be eagerly fetched.
not-found (optional - defaults to exception): specifies how foreign keys
that reference missing rows will be
handled. ignore will treat a missing
row as a null association.
entity-name (optional): the entity name of the associated class.
formula (optional): an SQL expression that defines the value for
a computed foreign key.
So something like this should do it:
<many-to-one name="Type" class="com.domain.ProcedureType" update="false" insert="false" fetch="join" lazy="false">
<column name="type" not-null="true" />
</many-to-one>
Reference
Hibernate Core documenation
5.1.12. Many-to-one
Something like this?
LEFT JOIN B on A.field1 = B.field2
Choose type of JOIN on your taste

NHibernate multiple primary keys mapping

I have a table called "Orderrow". Orderrow has a a compound primary key (CPK) with the following columns: OrderId, ProductId, RowNumber
OrderId and ProductId are also foreign keys refering to the tables Order and Product. The RowNumber is generated in the app.
I was wondering how this is mapped in NHibernate because I can only set 1 id element and 1 generator subelement.
Here is an example using the composite-id property in a NHibernate mapping file:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Domain" namespace="Domain.Model">
<class name="Program" table="program">
<composite-id>
<key-property name="Id" column="id"></key-property>
<key-property name="Prog" column="prog"></key-property>
<key-property name="Site" column="site"></key-property>
</composite-id>
<property name="ActiveDate" column="active_date"/>
<property name="Year" column="year"/>
</class>
</hibernate-mapping>
There is a 'composite-id' property you can use in your class mapping instead of the 'id' property. However, you should know that the nHibernate team strongly discourages the use of it. It sounds like you are dealing with a legacy database, in which you have no control over the schema. So, the 'composite-id' is specifically for your situation.
Check out the NH docs for more info: http://nhibernate.info/doc/nh/en/index.html
Personally I do not like to have compound primary keys in my database table schemas, plus they usually are 'hard' to handle by any ORM mapper I tried.
If I have to give a unique identity to a row in a table (especially if it represents a business object), I prefer to use a single value surrogate Id - a GUID or an Integer - if any of the fields in the table isn't suitable.
Using a composite Id is always troublesome when writing interrogation queries and joins, so my usual strategy is to use a surrogate Id (which has no meaning to the business object but to identify the object itself) and place a unique constraint on the fields of the previous CPK.

NHibernate mapping trouble

I have the following object model:
A top-level abstract class Element with many children and descendants.
A class Event.
Each Element contains a bag of Events.
Each Event has a pointer to the parent Element.
Up till now - pretty standart one-to-many relationship.
But, I want to use table per concrete class strategy. So, the class Element is not mapped to the database. I've tried to solve it this way: each of the concrete descendants of Element defines its own Bag of Events. The problem with this is that each <bag> element contains a <key> element. That key points to the Parent property of Event. It also makes the Parent column in the Events table a foreign key to the table which contains the Bag! But one column can't be a foreign key to several tables and I'm getting an exception on insert.
I've also tried to make the Parent field in the Events table a many-to-any kind of field. That worked. But when I want to make the relation bidirectional, meaning, to add the bags to the descendants of Element I come back to the same problem. Bag => foreign key => exception on insert.
I'm sure this case isn't as unique as it seems.
Thank you in advance for your help.
A little bit late, but I have some advise.
If you are using "table per concrete class", it is as if you would map completely independent tables. So you need separate foreign keys or many-to-any.
many-to-any stores the type name and NH knows to where the foreign key points. But it's impossible to have constraints on such a foreign key.
If you have several bags having items of the same type, make sure they all define different foreign keys:
<class name="A">
<!-- ... -->
<bag name="Events">
<key column="A_FK"/>
<one-to-many class="Event"/>
</bag>
</class>
<class name="B">
<!-- ... -->
<bag name="Events">
<key column="B_FK"/>
<one-to-many class="Event"/>
</bag>
</class>
You can have foreign key constraints on such a foreign key, but no not-null constraint, because only one of these foreign keys is used.
To really have only one foreign key with all the constraints, you need to map the element to a separate table.