I want to make a simple example for a
many-to-many mapping. Here are the mapping documents.
Mapping document:
A.hbm.xml
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class name="A" table="table_a">
<id name="id" type="long" unsaved-value="null" >
<column name="ID" sql-type="integer" not-null="true"/>
<generator class="hilo"/>
</id>
<!-- Name -->
<property name="name">
<column name="NAME" sql-type="varchar(32)" />
</property>
<!-- List of B - Bidirektionale Assoziation many-to-many -->
<list name="listOfB" table="table_a_b"
cascade="all-delete-orphan" lazy="true">
<key column="A_ID" />
<index column="LIST_INDEX" type="integer" />
<many-to-many class="B"
column="B_ID" />
</list>
</class>
</hibernate-mapping>
Mapping document:
B.hbm.xmlCode:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class name="B" table="table_b">
<id name="id" type="long" unsaved-value="null" >
<column name="ID" sql-type="integer" not-null="true"/>
<generator class="hilo"/>
</id>
<!-- Name -->
<property name="name">
<column name="NAME" sql-type="varchar(32)" />
</property>
<!-- List of A - Bidirektionale Assoziation many-to-many -->
<list name="listOfA" table="table_a_b" cascade="all-delete-orphan"
lazy="true">
<key column="B_ID" />
<index column="LIST_INDEX" type="integer" />
<many-to-many class="A" column="A_ID" />
</list>
</class>
</hibernate-mapping>
I want to have five instances of type A (aObj1, ... , aObj5) and five instances of type B (bObj1, ... , bObj5).
1. In the Collection of the
aObj1 I want to have references to
bObj1,
bObj2 and
bObj3.
2. In the Collection of the
aObj2 I want to have references to
bObj1 and
bObj4.
3. In the Collection of the
bObj1 I want to have references to
aObj1 and
aObj3.
4. In the Collection of the
bObj4 I want to have references to
aObj1 and
aObj3 too.
I use the java.util.ArrayList as Collection and the SchemaExport genaretes the following script for the table_a_b:
Code:
create table table_a_b (
A_ID INT8 not null,
B_ID INT8 not null,
LIST_INDEX INT4 not null,
primary key (B_ID, LIST_INDEX)
)
The primary key is B_ID and LIST_INDEX. The LIST_INDEX as part of primary key causes the problem (duplicate key) if I try to reference the Object
bObj1 from the Collection in the
aObj2, because the Collection in the
aObj1 as well as the Collection in the
aObj2 reference the same Object (bObj1) as the first Object (index = 0). For that reason I have twice the same primary key. My questions are:
1. Is it possibile to make the primary key in the
table_a_b from the A_ID and B_ID (without LIST_INDEX)?
2. How can I do it (what I described above) correctly?
3. Or, what is wrong in my code (mapping documents)?
Here is the class
A.java:
Code:
import java.util.*;
public class A
{
private Long id;
private String name;
private Collection listOfB;
public A()
{
this.listOfB = new ArrayList();
}
public Long getId()
{
return id;
}
public void setId(Long id)
{
this.id = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public Collection getListOfB()
{
return listOfB;
}
public void setListOfB(java.util.Collection listOfB)
{
this.listOfB = listOfB;
}
public void addInstanceOfB(B param)
{
this.listOfB.add(param);
}
public boolean removeInstanceOfB(B param)
{
return ((ArrayList) this.listOfB).remove(param);
}
}
The class
B.java is similar. And here is the code of the test method:
Code:
Transaction transaction = session.beginTransaction();
session.delete("from table_a in class A");
session.delete("from table_b in class B");
A aObj1 = new A();
aObj1.setName("aObj1");
A aObj2 = new A();
aObj2.setName("aObj2");
A aObj3 = new A();
aObj3.setName("aObj3");
A aObj4 = new A();
aObj4.setName("aObj4");
A aObj5 = new A();
aObj5.setName("aObj5");
B bObj1 = new B();
bObj1.setName("bObj1");
B bObj2 = new B();
bObj2.setName("bObj2");
B bObj3 = new B();
bObj3.setName("bObj3");
B bObj4 = new B();
bObj4.setName("bObj4");
B bObj5 = new B();
bObj5.setName("bObj5");
aObj1.addInstanceOfB(bObj1);
aObj1.addInstanceOfB(bObj2);
aObj1.addInstanceOfB(bObj3);
aObj2.addInstanceOfB(bObj1); // error because of fuplicate primary key in the table_a_b!!!
aObj2.addInstanceOfB(bObj4);
session.save(aObj1);
session.save(aObj2);
session.save(aObj3);
session.save(aObj4);
session.save(aObj5);
session.save(bObj1);
session.save(bObj2);
session.save(bObj3);
session.save(bObj4);
session.save(bObj5);
transaction.commit();
How can I do it correctly? Is there a logical error? Do I missunderstand something?
Thanks for any help.
P.S.
I use hibernate2.1 and PostgreSQL Database.