HHH-2060 : composite-id + generator
git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@14686 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
acb13ab513
commit
304673d721
|
@ -174,7 +174,7 @@ via Session.getIdentifier() -->
|
|||
key column. The class must implement java.io.Serializable and reimplement equals()
|
||||
and hashCode(). -->
|
||||
|
||||
<!ELEMENT composite-id ( meta*, (key-property|key-many-to-one)+ )>
|
||||
<!ELEMENT composite-id ( meta*, (key-property|key-many-to-one)+, generator? )>
|
||||
<!ATTLIST composite-id class CDATA #IMPLIED>
|
||||
<!ATTLIST composite-id mapped (true|false) "false">
|
||||
<!ATTLIST composite-id name CDATA #IMPLIED>
|
||||
|
|
|
@ -0,0 +1,505 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.test.cid;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
|
||||
import junit.framework.Test;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.junit.functional.FunctionalTestCase;
|
||||
import org.hibernate.junit.functional.FunctionalTestClassTestSuite;
|
||||
|
||||
/**
|
||||
* Tests the use of composite-id with a generator.
|
||||
* Test this behavior in all the various entity states (transient, managed, detached)
|
||||
* and the different state transitions.
|
||||
*
|
||||
* For HHH-2060.
|
||||
*
|
||||
* @author Jacob Robertson
|
||||
*/
|
||||
public class CompositeIdWithGeneratorTest extends FunctionalTestCase {
|
||||
|
||||
public CompositeIdWithGeneratorTest(String str) {
|
||||
super(str);
|
||||
}
|
||||
|
||||
public String[] getMappings() {
|
||||
return new String[] { "cid/PurchaseRecord.hbm.xml" };
|
||||
}
|
||||
|
||||
public static Test suite() {
|
||||
return new FunctionalTestClassTestSuite(CompositeIdWithGeneratorTest.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic test that id can be generated for composite-id.
|
||||
*/
|
||||
public void testCompositeIdSimple() {
|
||||
Session s = openSession();
|
||||
Transaction t = s.beginTransaction();
|
||||
|
||||
// persist the record to get the id generated
|
||||
PurchaseRecord record = new PurchaseRecord();
|
||||
s.persist(record);
|
||||
|
||||
t.commit();
|
||||
s.close();
|
||||
|
||||
// test that the id was generated
|
||||
PurchaseRecord.Id generatedId = record.getId();
|
||||
Date timestamp = record.getTimestamp();
|
||||
assertNotNull(generatedId);
|
||||
assertNotNull( generatedId.getPurchaseSequence() );
|
||||
assertTrue(generatedId.getPurchaseNumber() > 0);
|
||||
|
||||
s = openSession();
|
||||
t = s.beginTransaction();
|
||||
|
||||
// find the record, and see that the ids match
|
||||
PurchaseRecord find = (PurchaseRecord) s.get(PurchaseRecord.class, generatedId);
|
||||
assertNotNull(find);
|
||||
assertEquals( generatedId, find.getId() );
|
||||
assertEquals( timestamp, find.getTimestamp() );
|
||||
|
||||
t.commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
t = s.beginTransaction();
|
||||
|
||||
// generate another new record
|
||||
PurchaseRecord record2 = new PurchaseRecord();
|
||||
s.persist(record2);
|
||||
|
||||
t.commit();
|
||||
s.close();
|
||||
|
||||
PurchaseRecord.Id generatedId2 = record2.getId();
|
||||
Date timestamp2 = record2.getTimestamp();
|
||||
|
||||
s = openSession();
|
||||
t = s.beginTransaction();
|
||||
|
||||
PurchaseRecord find2 = (PurchaseRecord) s.get(PurchaseRecord.class, generatedId2);
|
||||
|
||||
t.commit();
|
||||
s.close();
|
||||
|
||||
// test that the ids are different
|
||||
PurchaseRecord.Id id1 = find.getId();
|
||||
PurchaseRecord.Id id2 = find2.getId();
|
||||
String seq1 = id1.getPurchaseSequence();
|
||||
String seq2 = id2.getPurchaseSequence();
|
||||
int num1 = id1.getPurchaseNumber();
|
||||
int num2 = id2.getPurchaseNumber();
|
||||
|
||||
assertEquals( timestamp2, find2.getTimestamp() );
|
||||
assertFalse( id1.equals(id2) );
|
||||
assertFalse( seq1.equals(seq2) );
|
||||
assertFalse(num1 == num2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the behavior of properties in detached objects.
|
||||
*/
|
||||
public void testDetachedProperty() {
|
||||
Session s = openSession();
|
||||
Transaction t = s.beginTransaction();
|
||||
|
||||
// persist the record
|
||||
PurchaseRecord record = new PurchaseRecord();
|
||||
s.persist(record);
|
||||
|
||||
// close session so we know the record is detached
|
||||
t.commit();
|
||||
s.close();
|
||||
|
||||
PurchaseRecord.Id generatedId = record.getId();
|
||||
|
||||
// change a non-id property, but do not persist
|
||||
Date persistedTimestamp = record.getTimestamp();
|
||||
Date newTimestamp = new Date(persistedTimestamp.getTime() + 1);
|
||||
record.setTimestamp(newTimestamp);
|
||||
|
||||
s = openSession();
|
||||
t = s.beginTransaction();
|
||||
|
||||
PurchaseRecord find = (PurchaseRecord) s.get(PurchaseRecord.class, generatedId);
|
||||
|
||||
t.commit();
|
||||
s.close();
|
||||
|
||||
// see that we get the original id, and the original timestamp
|
||||
assertEquals( generatedId, find.getId() );
|
||||
assertEquals( persistedTimestamp, find.getTimestamp() );
|
||||
|
||||
s = openSession();
|
||||
t = s.beginTransaction();
|
||||
|
||||
// update with the new timestamp
|
||||
s.update(record);
|
||||
|
||||
t.commit();
|
||||
s.close();
|
||||
|
||||
// find the newly updated record
|
||||
s = openSession();
|
||||
t = s.beginTransaction();
|
||||
|
||||
PurchaseRecord find2 = (PurchaseRecord) s.get(PurchaseRecord.class, generatedId);
|
||||
|
||||
t.commit();
|
||||
s.close();
|
||||
|
||||
// see that we get the original id, and the new timestamp
|
||||
assertEquals( generatedId, find2.getId() );
|
||||
assertEquals( newTimestamp, find2.getTimestamp() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the behavior of the id in detached objects.
|
||||
*/
|
||||
public void testDetachedId() {
|
||||
Session s = openSession();
|
||||
Transaction t = s.beginTransaction();
|
||||
|
||||
Date timestamp1 = new Date();
|
||||
Date timestamp2 = new Date(timestamp1.getTime() + 1);
|
||||
|
||||
// persist two records
|
||||
PurchaseRecord record1 = new PurchaseRecord();
|
||||
record1.setTimestamp(timestamp1);
|
||||
PurchaseRecord record2 = new PurchaseRecord();
|
||||
record2.setTimestamp(timestamp2);
|
||||
s.persist(record1);
|
||||
s.persist(record2);
|
||||
|
||||
// close session so we know the records are detached
|
||||
t.commit();
|
||||
s.close();
|
||||
|
||||
PurchaseRecord.Id generatedId1 = record1.getId();
|
||||
PurchaseRecord.Id generatedId2 = record2.getId();
|
||||
|
||||
// change the ids around - effectively making record1 have the same id as record2
|
||||
// do not persist yet
|
||||
PurchaseRecord.Id toChangeId1 = new PurchaseRecord.Id();
|
||||
toChangeId1.setPurchaseNumber( record2.getId().getPurchaseNumber() );
|
||||
toChangeId1.setPurchaseSequence( record2.getId().getPurchaseSequence() );
|
||||
record1.setId(toChangeId1);
|
||||
|
||||
s = openSession();
|
||||
t = s.beginTransaction();
|
||||
|
||||
PurchaseRecord find1 = (PurchaseRecord) s.get(PurchaseRecord.class, generatedId1);
|
||||
PurchaseRecord find2 = (PurchaseRecord) s.get(PurchaseRecord.class, generatedId2);
|
||||
|
||||
t.commit();
|
||||
s.close();
|
||||
|
||||
// see that we get the original ids (and timestamps)
|
||||
// i.e. weren't changed by changing the detached object
|
||||
assertEquals( generatedId1, find1.getId() );
|
||||
assertEquals( timestamp1, find1.getTimestamp() );
|
||||
assertEquals( generatedId2, find2.getId() );
|
||||
assertEquals( timestamp2, find2.getTimestamp() );
|
||||
|
||||
s = openSession();
|
||||
t = s.beginTransaction();
|
||||
|
||||
// update with the new changed record id
|
||||
s.update(record1);
|
||||
|
||||
t.commit();
|
||||
s.close();
|
||||
|
||||
// test that record1 did not get a new generated id, and kept record2's id
|
||||
PurchaseRecord.Id foundId1 = record1.getId();
|
||||
assertSame(toChangeId1, foundId1);
|
||||
assertEquals( toChangeId1.getPurchaseNumber(), foundId1.getPurchaseNumber() );
|
||||
assertEquals( toChangeId1.getPurchaseSequence(), foundId1.getPurchaseSequence() );
|
||||
|
||||
// find record 2 and see that it has the timestamp originally found in record 1
|
||||
s = openSession();
|
||||
t = s.beginTransaction();
|
||||
|
||||
find2 = (PurchaseRecord) s.get(PurchaseRecord.class, generatedId2);
|
||||
|
||||
t.commit();
|
||||
s.close();
|
||||
|
||||
// see that we get the original id (2), and the new timestamp (1)
|
||||
assertEquals( timestamp1, find2.getTimestamp() );
|
||||
assertEquals( generatedId2, find2.getId() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the behavior of saveOrUpdate (as opposed to calling "persist").
|
||||
*/
|
||||
public void testSaveOrUpdate() {
|
||||
Session s = openSession();
|
||||
Transaction t = s.beginTransaction();
|
||||
|
||||
Date timestamp1 = new Date();
|
||||
Date timestamp2 = new Date(timestamp1.getTime() + 1);
|
||||
|
||||
// persist the record
|
||||
PurchaseRecord record = new PurchaseRecord();
|
||||
record.setTimestamp(timestamp1);
|
||||
s.saveOrUpdate(record);
|
||||
|
||||
t.commit();
|
||||
s.close();
|
||||
|
||||
// test that the id was generated
|
||||
PurchaseRecord.Id generatedId = record.getId();
|
||||
assertNotNull(generatedId);
|
||||
assertNotNull( generatedId.getPurchaseSequence() );
|
||||
|
||||
// change the timestamp
|
||||
record.setTimestamp(timestamp2);
|
||||
|
||||
s = openSession();
|
||||
t = s.beginTransaction();
|
||||
|
||||
s.saveOrUpdate(record);
|
||||
|
||||
t.commit();
|
||||
s.close();
|
||||
|
||||
// see that we get the *same* id, and the new timestamp
|
||||
assertSame( generatedId, record.getId() );
|
||||
assertEquals( timestamp2, record.getTimestamp() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the behavior of load.
|
||||
*/
|
||||
public void testLoad() {
|
||||
Session s = openSession();
|
||||
Transaction t = s.beginTransaction();
|
||||
|
||||
// persist the record, then get the id and timestamp back
|
||||
PurchaseRecord record = new PurchaseRecord();
|
||||
s.persist(record);
|
||||
|
||||
t.commit();
|
||||
s.close();
|
||||
|
||||
PurchaseRecord.Id id = record.getId();
|
||||
Date timestamp = record.getTimestamp();
|
||||
|
||||
// using the given id, load a transient record
|
||||
PurchaseRecord toLoad = new PurchaseRecord();
|
||||
|
||||
s = openSession();
|
||||
t = s.beginTransaction();
|
||||
|
||||
s.load(toLoad, id);
|
||||
|
||||
t.commit();
|
||||
s.close();
|
||||
|
||||
// show that the correct timestamp and ids were loaded
|
||||
assertEquals( id, toLoad.getId() );
|
||||
assertEquals( timestamp, toLoad.getTimestamp() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the behavior of evict.
|
||||
*/
|
||||
public void testEvict() {
|
||||
Session s = openSession();
|
||||
Transaction t = s.beginTransaction();
|
||||
|
||||
Date timestamp1 = new Date();
|
||||
Date timestamp2 = new Date(timestamp1.getTime() + 1);
|
||||
|
||||
// persist the record, then evict it, then make changes to it ("within" the session)
|
||||
PurchaseRecord record = new PurchaseRecord();
|
||||
record.setTimestamp(timestamp1);
|
||||
s.persist(record);
|
||||
s.flush();
|
||||
s.evict(record);
|
||||
|
||||
record.setTimestamp(timestamp2);
|
||||
|
||||
t.commit();
|
||||
s.close();
|
||||
|
||||
PurchaseRecord.Id generatedId = record.getId();
|
||||
|
||||
// now, re-fetch the record and show that the timestamp change wasn't persisted
|
||||
s = openSession();
|
||||
t = s.beginTransaction();
|
||||
|
||||
PurchaseRecord persistent = (PurchaseRecord) s.get(PurchaseRecord.class, generatedId);
|
||||
|
||||
t.commit();
|
||||
s.close();
|
||||
|
||||
assertEquals( generatedId, persistent.getId() );
|
||||
assertEquals( timestamp1, persistent.getTimestamp() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the behavior of merge.
|
||||
*/
|
||||
public void testMerge() {
|
||||
Session s = openSession();
|
||||
Transaction t = s.beginTransaction();
|
||||
|
||||
Date timestamp1 = new Date();
|
||||
Date timestamp2 = new Date(timestamp1.getTime() + 1);
|
||||
|
||||
// persist the record
|
||||
PurchaseRecord record = new PurchaseRecord();
|
||||
s.persist(record);
|
||||
|
||||
t.commit();
|
||||
s.close();
|
||||
|
||||
// test that the id was generated
|
||||
PurchaseRecord.Id generatedId = record.getId();
|
||||
assertNotNull(generatedId);
|
||||
assertNotNull( generatedId.getPurchaseSequence() );
|
||||
|
||||
s = openSession();
|
||||
t = s.beginTransaction();
|
||||
|
||||
// update detached object, retrieve persistent object, then merge
|
||||
PurchaseRecord detached = record;
|
||||
detached.setTimestamp(timestamp2);
|
||||
PurchaseRecord persistent = (PurchaseRecord) s.get(PurchaseRecord.class, generatedId);
|
||||
|
||||
// show that the timestamp hasn't changed
|
||||
assertEquals( timestamp1, persistent.getTimestamp() );
|
||||
|
||||
s.merge(detached);
|
||||
|
||||
t.commit();
|
||||
s.close();
|
||||
|
||||
// show that the persistent object was changed only after the session flush
|
||||
assertEquals( timestamp2, persistent.getTimestamp() );
|
||||
|
||||
// show that the persistent store was updated - not just the in-memory object
|
||||
s = openSession();
|
||||
t = s.beginTransaction();
|
||||
|
||||
persistent = (PurchaseRecord) s.get(PurchaseRecord.class, generatedId);
|
||||
|
||||
t.commit();
|
||||
s.close();
|
||||
|
||||
assertEquals( timestamp2, persistent.getTimestamp() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the behavior of delete.
|
||||
*/
|
||||
public void testDelete() {
|
||||
Session s = openSession();
|
||||
Transaction t = s.beginTransaction();
|
||||
|
||||
// persist the record
|
||||
PurchaseRecord record = new PurchaseRecord();
|
||||
s.saveOrUpdate(record);
|
||||
|
||||
t.commit();
|
||||
s.close();
|
||||
|
||||
PurchaseRecord.Id generatedId = record.getId();
|
||||
|
||||
// re-fetch, then delete the record
|
||||
s = openSession();
|
||||
t = s.beginTransaction();
|
||||
|
||||
PurchaseRecord find = (PurchaseRecord) s.get(PurchaseRecord.class, generatedId);
|
||||
s.delete(find);
|
||||
assertFalse( s.contains(find) );
|
||||
|
||||
t.commit();
|
||||
s.close();
|
||||
|
||||
// attempt to re-fetch - show it was deleted
|
||||
s = openSession();
|
||||
t = s.beginTransaction();
|
||||
|
||||
find = (PurchaseRecord) s.get(PurchaseRecord.class, generatedId);
|
||||
|
||||
t.commit();
|
||||
s.close();
|
||||
|
||||
assertNull(find);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple test to demonstrate the ids can be generated even when using children.
|
||||
*/
|
||||
public void testGeneratedIdsWithChildren() {
|
||||
|
||||
Session s = openSession();
|
||||
Transaction t = s.beginTransaction();
|
||||
|
||||
// set up the record and details
|
||||
PurchaseRecord record = new PurchaseRecord();
|
||||
Set details = record.getDetails();
|
||||
details.add( new PurchaseDetail(record, "p@1", 1) );
|
||||
details.add( new PurchaseDetail(record, "p@2", 2) );
|
||||
|
||||
s.persist(record);
|
||||
|
||||
t.commit();
|
||||
s.close();
|
||||
|
||||
// show that the ids were generated (non-zero) and come out the same
|
||||
int foundPurchaseNumber = record.getId().getPurchaseNumber();
|
||||
String foundPurchaseSequence = record.getId().getPurchaseSequence();
|
||||
assertNotNull( record.getId() );
|
||||
assertTrue(foundPurchaseNumber > 0);
|
||||
assertNotNull(foundPurchaseSequence);
|
||||
|
||||
// search on detail1 by itself and show it got the parent's id
|
||||
s = openSession();
|
||||
t = s.beginTransaction();
|
||||
|
||||
// perform a find to show that it will wire together fine
|
||||
PurchaseRecord foundRecord = (PurchaseRecord) s.get(PurchaseRecord.class,
|
||||
new PurchaseRecord.Id(foundPurchaseNumber, foundPurchaseSequence)
|
||||
);
|
||||
|
||||
t.commit();
|
||||
s.close();
|
||||
|
||||
// some simple test to see it fetched
|
||||
assertEquals( 2, foundRecord.getDetails().size() );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.test.cid;
|
||||
|
||||
|
||||
/**
|
||||
* @author Jacob Robertson
|
||||
*/
|
||||
public class PurchaseDetail {
|
||||
|
||||
private PurchaseRecord purchaseRecord;
|
||||
|
||||
private String productId;
|
||||
private int quantity;
|
||||
|
||||
public PurchaseDetail(PurchaseRecord record, String productId, int quantity) {
|
||||
this.productId = productId;
|
||||
this.quantity = quantity;
|
||||
this.purchaseRecord = record;
|
||||
}
|
||||
public PurchaseDetail() {}
|
||||
|
||||
|
||||
/**
|
||||
* @return the purchaseRecord
|
||||
*/
|
||||
public PurchaseRecord getPurchaseRecord() {
|
||||
return purchaseRecord;
|
||||
}
|
||||
/**
|
||||
* @param purchaseRecord the purchaseRecord to set
|
||||
*/
|
||||
public void setPurchaseRecord(PurchaseRecord purchaseRecord) {
|
||||
this.purchaseRecord = purchaseRecord;
|
||||
}
|
||||
/**
|
||||
* @return the quantity
|
||||
*/
|
||||
public int getQuantity() {
|
||||
return quantity;
|
||||
}
|
||||
/**
|
||||
* @param quantity the quantity to set
|
||||
*/
|
||||
public void setQuantity(int quantity) {
|
||||
this.quantity = quantity;
|
||||
}
|
||||
/**
|
||||
* @return the productId
|
||||
*/
|
||||
public String getProductId() {
|
||||
return productId;
|
||||
}
|
||||
/**
|
||||
* @param productId the productId to set
|
||||
*/
|
||||
public void setProductId(String productId) {
|
||||
this.productId = productId;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
~ Hibernate, Relational Persistence for Idiomatic Java
|
||||
~
|
||||
~ Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
~ indicated by the @author tags or express copyright attribution
|
||||
~ statements applied by the authors. All third-party contributions are
|
||||
~ distributed under license by Red Hat Middleware LLC.
|
||||
~
|
||||
~ This copyrighted material is made available to anyone wishing to use, modify,
|
||||
~ copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
~ Lesser General Public License, as published by the Free Software Foundation.
|
||||
~
|
||||
~ This program is distributed in the hope that it will be useful,
|
||||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
~ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
~ for more details.
|
||||
~
|
||||
~ You should have received a copy of the GNU Lesser General Public License
|
||||
~ along with this distribution; if not, write to:
|
||||
~ Free Software Foundation, Inc.
|
||||
~ 51 Franklin Street, Fifth Floor
|
||||
~ Boston, MA 02110-1301 USA
|
||||
-->
|
||||
|
||||
<!DOCTYPE hibernate-mapping PUBLIC
|
||||
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
|
||||
|
||||
<!--
|
||||
|
||||
This mapping demonstrates composite-id using a generator.
|
||||
|
||||
-->
|
||||
|
||||
<hibernate-mapping package="org.hibernate.test.cid">
|
||||
|
||||
<class name="PurchaseRecord">
|
||||
|
||||
<composite-id name="id"
|
||||
class="PurchaseRecord$Id">
|
||||
<key-property name="purchaseNumber"/>
|
||||
<key-property name="purchaseSequence"/>
|
||||
<generator class="org.hibernate.test.cid.PurchaseRecordIdGenerator"/>
|
||||
</composite-id>
|
||||
|
||||
<set name="details"
|
||||
lazy="false"
|
||||
inverse="true"
|
||||
cascade="all">
|
||||
<key>
|
||||
<column name="purchaseNumber"/>
|
||||
<column name="purchaseSequence"/>
|
||||
</key>
|
||||
<one-to-many class="PurchaseDetail"/>
|
||||
</set>
|
||||
|
||||
<property name="timestamp" column="timestamp"/>
|
||||
|
||||
</class>
|
||||
|
||||
<class name="PurchaseDetail">
|
||||
|
||||
<id name="productId"
|
||||
type="string"
|
||||
column="productId">
|
||||
<generator class="assigned"/>
|
||||
</id>
|
||||
|
||||
<property name="quantity"/>
|
||||
|
||||
<many-to-one name="purchaseRecord"
|
||||
class="PurchaseRecord"
|
||||
not-null="true">
|
||||
<column name="purchaseNumber"/>
|
||||
<column name="purchaseSequence"/>
|
||||
</many-to-one>
|
||||
|
||||
</class>
|
||||
|
||||
</hibernate-mapping>
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.test.cid;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Jacob Robertson
|
||||
*/
|
||||
public class PurchaseRecord {
|
||||
public static class Id implements Serializable {
|
||||
private int purchaseNumber;
|
||||
private String purchaseSequence;
|
||||
|
||||
public Id(int purchaseNumber, String purchaseSequence) {
|
||||
this.purchaseNumber = purchaseNumber;
|
||||
this.purchaseSequence = purchaseSequence;
|
||||
}
|
||||
public Id() {}
|
||||
|
||||
/**
|
||||
* @return Returns the purchaseNumber.
|
||||
*/
|
||||
public int getPurchaseNumber() {
|
||||
return purchaseNumber;
|
||||
}
|
||||
/**
|
||||
* @param purchaseNumber The purchaseNumber to set.
|
||||
*/
|
||||
public void setPurchaseNumber(int purchaseNumber) {
|
||||
this.purchaseNumber = purchaseNumber;
|
||||
}
|
||||
/**
|
||||
* @return the purchaseSequence
|
||||
*/
|
||||
public String getPurchaseSequence() {
|
||||
return purchaseSequence;
|
||||
}
|
||||
/**
|
||||
* @param purchaseSequence the purchaseSequence to set
|
||||
*/
|
||||
public void setPurchaseSequence(String purchaseSequence) {
|
||||
this.purchaseSequence = purchaseSequence;
|
||||
}
|
||||
public int hashCode() {
|
||||
return purchaseNumber + purchaseSequence.hashCode();
|
||||
}
|
||||
public boolean equals(Object other) {
|
||||
if (other instanceof Id) {
|
||||
Id that = (Id) other;
|
||||
return purchaseSequence.equals(this.purchaseSequence) &&
|
||||
that.purchaseNumber == this.purchaseNumber;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Id id;
|
||||
private Date timestamp = new Date();
|
||||
private Set details = new HashSet();
|
||||
|
||||
public PurchaseRecord() {}
|
||||
|
||||
/**
|
||||
* @return Returns the id.
|
||||
*/
|
||||
public Id getId() {
|
||||
return id;
|
||||
}
|
||||
/**
|
||||
* @param id The id to set.
|
||||
*/
|
||||
public void setId(Id id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the details
|
||||
*/
|
||||
public Set getDetails() {
|
||||
return details;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param details the details to set
|
||||
*/
|
||||
public void setDetails(Set details) {
|
||||
this.details = details;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the timestamp
|
||||
*/
|
||||
public Date getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param timestamp the timestamp to set
|
||||
*/
|
||||
public void setTimestamp(Date timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.test.cid;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.hibernate.engine.SessionImplementor;
|
||||
import org.hibernate.id.IdentityGenerator;
|
||||
|
||||
/**
|
||||
* Simple {@link IdentityGenerator} implementation for testing composite-id.
|
||||
*
|
||||
* @author Jacob Robertson
|
||||
*/
|
||||
public class PurchaseRecordIdGenerator extends IdentityGenerator {
|
||||
|
||||
private static int nextPurchaseNumber = 2;
|
||||
private static int nextPurchaseSequence = 3;
|
||||
|
||||
public Serializable generate(SessionImplementor s, Object obj) {
|
||||
return new PurchaseRecord.Id(
|
||||
nextPurchaseNumber++,
|
||||
String.valueOf(nextPurchaseSequence++));
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue