joining two tables with differnt join column names - sql

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

Related

ManyToOne() with InnerJoin on Custom Column

Is there a way to map property with database column with custom column, that IS NOT a FK, just a candidate key ( it is unique for table )?
If not, what is my options here? (need to restrict select results with joined table restrictions)
NHibernate supports feature called property-ref. It is documented here: 5.1.10. many-to-one. Some extract:
The property-ref attribute should only be used for mapping legacy data
where a foreign key refers to a unique key of the associated table
other than the primary key. This is an ugly relational model. For
example, suppose the Product class had a unique serial number, that is
not the primary key. (The unique attribute controls NHibernate's DDL
generation with the SchemaExport tool.)
So, if the child table contains for example Guid, which is the same as in the target parent table... this could solve the issue. Example mapping:
<many-to-one name="Parent" property-ref="ParentGuid" column="THE_GUID_COLUMN"/>
Using the fluent syntax, it could look like this:
References(x => x.Parent)
...
.PropertyRef("ParentGuid")
.Column("THE_GUID_COLUMN");
Anyhow, this is not ideal and should be used mostly for solving legacy stuff.

Unique names in primary keys

I have db tables in each I have same primary column name ('ID')
I get error from nhibernate:
System.IndexOutOfRangeException : An SqlCeParameter with
ParameterIndex '5' is not contained by this SqlCeParameterCollection
When I change these columns names to unique names, all is ok.
But i wonder how to fix it without name changes. I simply want same name in each table.
<class name="AppSignature" table="app_signatures" lazy="true">
<id name="Id"><generator class="guid"></generator></id>
</class>
<class name="AppState" table="app_states" lazy="true">
<id name="Id"><generator class="guid"></generator></id>
<many-to-one name="app_signature"
class="AppSignature"
column="Id"
foreign-key="id_fom_app_signature"
not-null="true"
>
</many-to-one>
</class>
Many-to-one relation means that an AppState instance can be assigned at most to one AppSignature instance. To an AppSignature can be assigned any number of AppState instances. This relation is implemented as an foreign key from app_states table to app_signatures table. "Column" attribute in "many-to-one" element determines column name that stores a value for the foreign key. To the Id column are mapped two AppState members: Id and app_signature which is not possible in NH and leads to the described exception.
The fix is easy:
<many-to-one name="app_signature"
class="AppSignature"
column="app_signature_id"
foreign-key="id_fom_app_signature"
not-null="true"
>
</many-to-one>
Name of column that implements foreign key was changed to an unique name: "app_signature_id". Now app_signature member is mapped to AppState.app_signature_id column which points to the app_signatures.Id column
However described exception should disappear (if the new column is properly added to app_signatures table) it would not necessarily be what you you really want. The relation between AppState and AppSignature could be one-to-one. It means an AppState instnace can be assigned to a single AppSignature instnance and vice versa. Such relation could be implemented by a primary and foreign key on the same column. There is a very nice article about one-to-one relations.

Nhibernate - Generate schema without forign key

For our test fixtures we use NHibernate to generate a database schema. We have a slight strange case in which an entity references a another entity but we don't wish to have a foreign key constraint (it should be possible to delete the referenced entity so a foreign key cannot be used).
Is it possible to specify that the generated schema does not have a foreign key for a particular relationship?
Jay-
If you're using Fluent NHibernate, you can set this in either your implementation of IHasManyConvention or IReferenceConvention (if using conventions).
Cascade.SaveUpdate() should propagate the saves and updates, but leave the orphaned child objects when the parents are deleted.
In standard NHibernate HBM files, I believe the tag for a bag should look like:
<bag cascade="save-update" name="EntityName"> ... </bag>
UPDATE: Here's an informational post by Ayende on the topic of orphaning child objects and the differences with the cascade values.

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.