I have two table to be joined using hbm file.
The scenario is as follows
Table B has a composite PK.
Table B
a1 (pk)
a2 (pk)
a3 (pk)
foo
bar
========
Table A has a primary key and is a foreign key from Table B
Table A
a1 (pk,fk)
hip
hop
========
This a one to many relation from Table A to B.
Can any one help me out with the hbm file mapping?
I am jotting down wot i have tried.
For Table B
<class>
<composite-id name="XXXX" class=".....">
<key-property name="a1" column="a1" type="int"/>
<key-property name="a2" column="a2" type="int"/>
<key-property name="a3" column="a3" type="int"/>
</composite-id>
<property name="foo" column="foo" type="java.lang.Float"></property>
<property name="bar" column="bar" type="java.lang.Float"></property>
</class>
For Table A
Normal hibernate mapping.
How to join both tables?
a workaround could be afake propertyref to break out of the compositeId
<class class="B">
<property name="a1_again" column="a1" insert="false" update="false"/>
<bag name="As" class="A">
<key property-ref="a1_again"></key>
...
</bag>
</class>
Related
How to insert auto_increment in an already created table in liquibase?
User table already exists.
<createTable tableName="user">
<column name="user" type="varchar(255)">
<constraint nullable="false">
</column>
<column name="user_id" type="varchar(255)"/>
<column name="password" type="varchar(255)"/>
<column name="email" type="varchar(255)"/>
</createTable>
<addPrimaryKey tableName="user"> columnNames="user" constraintName="user_pk">
Duplicate user occurred in userTable.
The pk was removed because the user could have a duplicate name.
However, since we need to have the value of #Id, if we add the ID and set the autoIncrement, there will be a problem.
<dropPrimaryKey tableName="user"/>
<addColumn tableName="user">
<column name="id" type="BIGINT"/>
</addColumn>
<createSequence
incrementBy="1"
maxValue="9223372036854775807"
minValue="1"
startValue="1"
sequenceName="user_sequence"/>
Error Message
Reason: liquibase.exception.DatabaseException: ERROR: column "id" of relation "user" contains null values [Failed SQL: (0) ALTER TABLE "public"."user" ADD CONSTRAINT "PK_user" PRIMARY KEY ("id")]
Please check this SO post.
<changeSet id="1" author="Me">
<dropPrimaryKey tableName="tv_campaigns"/>
<addColumn tableName="tv_campaigns">
<column name="ID" type="bigint(20)" autoIncrement="true">
<constraints nullable="false" primaryKey="true" unique="true"/>
</column>
</addColumn>
<addAutoIncrement tableName="tv_campaigns" columnName="ID" columnDataType="bigint(20)"/>
</changeSet>
Try using the addAutoIncrement tag, read more about it here.
<many-to-one name="attachment" class="AttachmentEntity" lazy="false"
fetch="select" cascade="delete">
<column name="SPA_ATTACHMENT_ID" not-null="true" unique-key="IDX_AMT_COND_01"/>
</many-to-one>
What is the Unique Key doing and how will it work as a string?
As per the JBoss documentation,
A unique-key attribute can be used to group columns in a single,
unique key constraint. The attribute overrides the name of any
generated unique key constraint.
Typical use case for unique-key would be, when you want the values of multiple columns as a whole to be unique.
For example:
class Department {...}
class Employee {
Integer employeeId;
Department department;
}
So, to ensure that 2 Employee objects with same employeeId and department are not persisted, we can use the unique-key attribute with same value EmpIdDept on the 2 columns EMP_ID and DEPT_ID to enforce the uniqueness constraint on them as a whole:
<property name="employeeId" column="EMP_ID" unique-key="EmpIdDept"/>
<many-to-one name="department" column="DEPT_ID" class="Department" unique-key="EmpIdDept"/>
The string specified as the attribute value, i.e. IDX_AMT_COND_01 in your case, is just the name of the multi column unique constraint.
Also check this answer and this one (to achieve the same using #UniqueConstraint)
NOTE: to use single column unique constraint, you need to use
unique="true"
I have two tables, say:
PAYMENT
------------------------------
OrderId INT PK
PaymentId INT PK
Amount FLOAT
ChildPaymentRowNum INT
CARD_PAYMENT
------------------------------
OrderId INT PK
PaymentRowNum INT PK
CardType STRING
CHEQUE_PAYMENT
------------------------------
OrderId INT PK
PaymentRowNum INT PK
CheckNumber INT
No, I didn't make this DB and no I can't change it. I want to map CARD_PAYMENT and CHEQUE_PAYMENT as joined-subclasses of PAYMENT. The difference in this model from the examples I've found is that I'm both using a composite key and one of the column names in the foreign table doesn't match.
I think if it were not a composite key I could do this:
<joined-subclass name="CardPayment" table="CARD_PAYMENT" extends="Payment">
<key column="PaymentRowNum" foreign-key="ChildPaymentRowNum">
</joined-subclass>
And if the names matched on the composite key I could do this:
<joined-subclass name="CardPayment" table="CARD_PAYMENT" extends="Payment">
<key>
<column="OrderId">
<column="PaymentRowNum">
</key>
</joined-subclass>
But, while I'd like to do something like this I'm pretty sure it's illegal:
<!-- NO GOOD -->
<joined-subclass name="CardPayment" table="CARD_PAYMENT" extends="Payment">
<key>
<column="OrderId" foreign-key="OrderId">
<column="PaymentRowNum" foreign-key="ChildPaymentRowNum">
</key>
</joined-subclass>
So, how would I do something like this?
BONUS POINTS: if you can tell me how to do it with NHibernate.Mapping.Attributes, but if not I can probably figure it out.
The foreign-key attribute is used to specify the name of a foreign key constraint (not column!) that should be created by the NHibernate schema generation tool. It has no affect on NHibernate during runtime.
Why do you want to specify the key column name of the base class in the subclass key? Even the NHibernate documentation for joined-subclass uses different column names in both tables: http://nhibernate.info/doc/nh/en/index.html#mapping-declaration-joinedsubclass
I've got the following two tables:
Jobs
--------
JobNo
DivisionID
NCRs
--------
ID
JobNo
SpoilageJobNo
DivisionID
JobNo and DivisionID make up a composite key in the Jobs table (I know, but unfortunately it has to be a composite key, as it's actually a view that's pulling data from 4 different databases), and I need to join this key to the NCRs table on both JobNo and SpoilageJobNo.
I've tried the following mappings:
<class name="Job" table="v_Jobs">
<composite-id name="Key">
<key-property name="JobNo"></key-property>
<key-many-to-one name="Division" class="Division" column="DivisionID"/>
</composite-id>
<bag name="NCRs">
<key>
<column name="JobNo"></column>
<column name="DivisionID"></column>
</key>
<one-to-many class="NCR"/>
</bag>
<bag name="SpoilageNCRs">
<key>
<column name="SpoilageJobNo"></column>
<column name="DivisionID"></column>
</key>
<one-to-many class="NCR"/>
</bag>
</class>
<class name="NCR" table="NCRs">
<id name="ID">
<generator class="identity"></generator>
</id>
<many-to-one name="Division"
class="Division"
column="DivisionID">
</many-to-one>
<many-to-one name="Job"
class="Job"
column="JobNo">
</many-to-one>
<many-to-one name="SpoilageJob"
class="Job"
column="SpoilageJobNo">
</many-to-one>
</class>
But I just get the error Foreign key (FK480F1031931B2CA4:NCRs [JobNo])) must have same number of columns as the referenced primary key (v_Jobs [JobNo, DivisionID])
This is the answer Tom posted to his question:
Ah ha, think I've got it. I've updated my mappings for the NCR with this:
<many-to-one name="Job" class="Job">
<column name="JobNo"></column>
<column name="DivisionID"></column>
</many-to-one>
<many-to-one name="SpoilageJob" class="Job">
<column name="SpoilageJobNo"></column>
<column name="DivisionID"></column>
</many-to-one>
Can someone tell me how to accomplish this mapping using Fluent NHibernate? It's simply an account table with a composite key, that has many child accounts in a conjunction table.
Here's the working NHibernate mapping and the create SQL it generates:
<?xml version="1.0"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true">
<class name="NHibernateM2M000.Account, NHibernateM2M000" lazy="false">
<composite-id>
<key-property type="Int32" name="AccountId" />
<key-property type="Char" name="AccountTypeAbbr" />
</composite-id>
<property name="Name" column="AccountName" />
<bag name="ChildAccounts" lazy="false" table="AccountXref">
<key>
<column name="ParentAccountId" sql-type="int" />
<column name="ParentAccountTyper" sql-type="nchar" length="1" />
</key>
<many-to-many class="NHibernateM2M000.Account, NHibernateM2M000">
<column name="ChildAccountId" sql-type="int"/>
<column name="ChildAccountType" sql-type="nchar" length="1" />
</many-to-many>
</bag>
</class>
create table Account (AccountId INT not null, AccountTypeAbbr NCHAR(1) not null, AccountName NVARCHAR(255) null, primary key (AccountId, AccountTypeAbbr))
create table AccountXref (ParentAccountId int not null, ParentAccountTyper nchar not null, ChildAccountId int not null, ChildAccountType nchar not null)
alter table AccountXref add constraint FKB769F8B52F1320AB foreign key (ChildAccountId, ChildAccountType) references Account
alter table AccountXref add constraint FKB769F8B5A2DB3DC7 foreign key (ParentAccountId, ParentAccountTyper) references Account
I believe after looking at Fluent NHibernate at the time of this posting and now, that it's not possible. Dropping into the .hbm file is the only way to accomplish what I wanted here.