Consider three tables. Interest date can come from Master document or Manual Override. If it from Master Document, the master_doc_id carries the reference and if it comes from manual override manual_override_id carries the reference
INTEREST_RATE
id,
rate,
master_doc_id,
manual_override_id
MASTER_DOC
id,
<Master doc related fields>
MANUAL_OVERRIDE
id,
<Manual Overide related fields>
Interest rate comes from either Master doc or manual override. Meaning, either one can have an id, and the other null. Never will both have values, or will both be null
Both MasterDoc and ManualOverride provide one-to-many mapping to Interest
MasterDoc
<set access="field" name="interestRates" inverse="false" cascade="all-delete-orphan">
<cache usage="read-write"/>
<key column="MASTER_DOC_ID"/>
<one-to-many class="com.foo.foos.InterestRate"/>
</set>
ManualOverRide
<set access="field" name="interestRates" inverse="false" cascade="all-delete-orphan">
<cache usage="read-write"/>
<key column="MANUAL_OVERRIDE_ID"/>
<one-to-many class="com.foo.foos.InterestRate"/>
</set>
This works fine.
But, i need to enforce the contstraint that, either of them has to have a value and the other null.
I tried.
Obvious not-null in one-to-many mapping. Obvious that this will fail because, both columns cant have values together.
Constraint on the table, (in the database). But, hibernate creates an insert followed by an update on the table. Even though the final result would be valid, the constraint will fail after the initial insert.
ex:
while uploading the initial file
insert into master_doc......
insert into interest_rate.... (with null values in master_doc_id and manual_override_id)
update interest_rate (set master_doc_id = id of master_doc)
The constraint fails on line no 2.
Any way I can get this to work. I need to have this constraint in place, to prevent manual updates on the table.
Related
org.hibernate.StaleStateException
Is thrown sometimes (not consistent) in unit test case.
The normal flow is:
Create
Update
Delete
StaleStateException is thrown while executing delete operation.
The entity has child entities with one to many relationship:
<set name="child" cascade="delete, all,delete-orphan" inverse="true"
lazy="true">
<cache usage="nonstrict-read-write"/>
<key column="COLUMN"/>
<one-to-many class="CHILDClass"/>
</set>
And the cache strategy is "nonstrict-read-write"
Not sure of its issue due to second level cache, as the exception is not consistent.
How to fix this issue and what extra details I need to check to fix this issue.
I'm working with Hibernate 3.6 version, with xml mapping files. In my case I have three mapped entities, which are Detector, Antenna and Location. Basically, having Detector->Set<Antenna> and Location->Set<Antenna> relations, I would like to have also Detector->Set<Location> available.
Each Detector has a Set of Antenna entities, mapped like that:
<set name="_Antennas" table="tantenna" inverse="true" cascade="all">
<key>
<column name="id_detector" not-null="true" />
</key>
<one-to-many class="Antenna" />
</set>
Also each Antenna belongs to a specific Location and to a specific Detector. That's the many-to-one mapping to refer that:
<many-to-one name="_Detector" class="com.tadic.model.detector.Detector"
column="id_detector" />
<many-to-one name="_Location" class="com.tadic.model.location.Location"
column="id_location" />
In the same way, Location has a Set of its Antennas:
<set name="_Antennas" table="tantenna">
<key>
<column name="id_location" />
</key>
<one-to-many class="com.tadic.model.detector.Antenna" />
</set>
So Detector knows about its Antennas, Antennas know about their Detector and Location. Location entity has a set of its Antennas, but tlocation table has no foreign-keys.
However, I'm interested in knowing all the Locations of a Detector in a specific point. I know I can do it writing an HQL, but I would like to know if this is possible when Detector loads, just mapping it as a Set of Location entities.
Remember tlocation table has no iddetector column to link it with, also I think there's no need for it.
If I got it right from a database point
tdetector [1]--[id_detector]-->[n] tantenna
tlocation [1]--[id_location]-->[m] tantenna
Meaning tantenna has a column tuple of (id_detector, id_location) and is essentially a link table between tdetector and tlocation. This could be used to facilitate a many-to-many mapping between Detectors and Locations.
And here is the mapping fragment for the Detector hibernate mapping.
<set name="locations" table="tantenna">
<key column="id_detector" />
<many-to-many class="com.tadic.model.location.Location" column="id_location" />
</set>
One more thing. In my experience, having such a complex relations scheme mapped on the ORM does not come without cost. Even if hibernate finds your mapping files to be fine during the session factory initialization, I urge you to test thoroughly and, if necessary, specify some relations to be read-only (i.e. only useful when reading data) with insert="false" update="false".
I have the following entity in hbm.xml file
<class name="Base" table="base">
<id name="id"/>
<list name="ips" cascade="all-delete-orphan" lazy="false" fetch="join">
<cache usage="read-write" include="all" />
<key column="base_id" />
<list-index column="ip_order"/>
<element column="ip" type="string"/>
</list>
</class>
i have one entity Base with two ips string in the collection.
when i make:
session.createCriteria(base.class).list();
the result is two Base object
when i make:
session.createQuery(" from Base").list();
the result is one entity Base.
can someone tell me why i have this situation?
As per your mapping xml Base is one table and ips(IP) is another table.
One Base having two List(ips) means Base table will have one entry in DB(base table).
IP will have two entries in DB (ip table).
Obvisully Base table will have only one entry.
Check this example
I bet there are 2 records in the table for ips.
As you have declare ips being eager fetched, so it will also join fetch the ips when you are creating the criteria to fetch Base.class, causing the "result set" contains 2 records. However, the two "records" are in fact same instance.
The way to solve is simple though, search for use of DISTINCT_ROOT_ENTITY result transformer.
I have the following DB schema :
table a {
id,
state
}
table b {
id,
a_id,
is_valid,
amount
}
I want to have a hibernate mapping where I fetch values from table b only if a.state has a certain value. This is the hibernate mapping i had (used the example from the jBoss Documentation)
<discriminator column="state" type="string"/>
<subclass name="ClassB" discriminator-value="VALUE1">
<join table="b">
<key column="a_id"/>
<property name="amount" column="amount"/>
</join>
</subclass>
When i did this, my xml showed a syntax error stating that a hierarchy must be followed.
Is what I'm doing correct and if not, it would be great if someone could show me the way forward. Thanks.
P.S - more than one entry in table b will have the a_id column. However only one row in b will have the is_valid value set and its enough if i get this row in my POJO
It looks to me like you are mapping a table per subclass with discriminator strategy. This would imply a 1 - 1 row correlation between table a and table b, where the primary key of table b (the subclass) would also be a foreign key into table a.
However, your mapping is slightly odd in that you have
<key column="a_id" />
Typically this should be
<key column="id" />
And there would be no "a_id" column.
However, your db design looks like a one-to-many relationship rather than a subclass relationship.
Without your objects themselves, i can't really say what it is you're trying to do.
Take a look at the hibernate docs on inheritence.
http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html/inheritance.html
I have a User and a set of Authorities in a one-to-many relationship:
User.hbm.xml:
<set name="authorities" table="authorities" cascade="all-delete-orphan">
<key column="user_id" />
<one-to-many class="com.ebisent.domain.Authority" />
</set>
When I delete a user, I want to delete the authorities as well, but what is happening is that the child table's foreign key (authorities.user_id) is set to null instead. Then I get the following error and the User delete is rolled back:
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1
The authorities.user_id update to null is not rolled back, however.
How can I delete Authorities when I delete the parent User?
EDIT:
I got this working by explicitly deleting the authorities, calling refresh() on the user, then deleting the user, but I would like to know the "right" way to do this.
This is weird, a cascade all-delete-orphan should cascade the delete operation from the parent to the children. So the following should suffice to get the children deleted:
Parent p = (Parent) session.load(Parent.class, pid);
session.delete(p);
session.flush();
Do you get a different result when using all,delete-orphan or even more simply delete (you shouldn't). Is the assocation bidirectional? If yes, could you show the other side and the corresponding mapping?
The association is only from parent to child, and I get the same results with all, delete-orphan, and delete, BUT...I didn't have session.flush(), and that appears to solve the problem.
The explicit flush might help. But it shouldn't be necessary. I think that defining the foreign key as non nullable would help to get the correct behavior:
<set name="authorities" table="authorities" cascade="all-delete-orphan">
<key column="user_id" not-null="true"/>
<one-to-many class="com.ebisent.domain.Authority" />
</set>
Not tested though.