Ok, I finally got a chance to throw a quick example together.
It seems that hibernate3 will save the information to the database just fine.
The problem is when it reads the information back from the DB.
If the component has only collections, the component will allways be null.
or
If the component contains non-null collections, but the columns in the parent table is null , the component is allways null.
This works fine in Hibernate 2.1.x. I have code that was ported to Hibernate3, but I had to port it back to 2.1.8 due to this issue.
This will replicate the issue:
Hibernate Properties file
hibernate.connection.driver_class = com.mysql.jdbc.Driver
hibernate.connection.url = jdbc:mysql://localhost/testdb
hibernate.connection.username =
hibernate.connection.password =
hibernate.dialect = org.hibernate.dialect.MySQLInnoDBDialect
SQL table creation
Code:
SET FOREIGN_KEY_CHECKS=0;
USE `testdb`;
#
# Structure for the `_compitems` table :
#
CREATE TABLE `_compitems` (
`_parentId` int(11) NOT NULL default '0',
`_test` varchar(255) default NULL,
`_number` int(11) default NULL,
`_indexName` varchar(255) NOT NULL default '',
PRIMARY KEY (`_parentId`,`_indexName`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
#
# Structure for the `_hibparent` table :
#
CREATE TABLE `_hibparent` (
`_id` int(11) NOT NULL auto_increment,
`_parentName` varchar(255) default NULL,
`_someValue` int(11) NOT NULL default '0',
`_compName` varchar(255) default NULL,
PRIMARY KEY (`_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Mapping Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping SYSTEM "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="test.hibernate.Parent" table="_hibParent">
<id name="id" column="_id" type="int" unsaved-value="0">
<generator class="native"/>
</id>
<property name="parentName" column="_parentName" type="string" length="255" access="property" insert="true" update="true" not-null="false"/>
<property name="someValue" column="_someValue" type="int" access="property" insert="true" update="true" not-null="true"/>
<component name="component" class="test.hibernate.Component" lazy="false" insert="true" update="true">
<property name="compName" column="_compName" type="string" length="255" access="property" insert="true" update="true" not-null="false"/>
<map cascade="all" inverse="false" lazy="false" name="mapItems" sort="unsorted" table="_compItems" access="property" outer-join="true">
<key column="_parentId"/>
<index column="_indexName" type="string"/>
<composite-element class="test.hibernate.MapItem">
<property access="property" column="_test" insert="true" name="text" not-null="false" type="string" unique="false" update="true"/>
<property access="property" column="_number" insert="true" name="number" not-null="false" type="int" unique="false" update="true"/>
</composite-element>
</map>
</component>
</class>
</hibernate-mapping>
H3MapTest.java Code:
package test.hibernate;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.dialect.MySQLInnoDBDialect;
public class H3MapTest
{
public H3MapTest()
{
super();
}
public static void main(String[] args) throws Exception
{
Configuration cfg = new Configuration()
.addClass(Parent.class);
SessionFactory factory = cfg.buildSessionFactory();
Session sess = factory.openSession();
Transaction tr = sess.beginTransaction();
Parent workingParent = createWorking();
Parent problemParent = createComponentProblem1();
sess.save(workingParent);
sess.save(problemParent);
tr.commit();
sess.close();
sess = factory.openSession();
tr = sess.beginTransaction();
Query aQuery = sess.createQuery("from Parent");
List aList = aQuery.list();
for (Iterator iter = aList.iterator(); iter.hasNext();)
{
Parent element = (Parent) iter.next();
sess.delete(element);
}
tr.commit();
sess.close();
}
public static Parent createWorking()
{
Parent aParent = new Parent();
aParent.setParentName("Working");
aParent.setSomeValue(50);
Component aComp = new Component();
//Because this is null, the component map will not be loaded back out
aComp.setCompName("aComponent");
Map aCompMap = new HashMap(2);
aCompMap.put(aParent.getParentName() + "compIndex1", new MapItem(10, aParent.getParentName() + "compIndex1 text"));
aCompMap.put(aParent.getParentName() + "compIndex2", new MapItem(20, aParent.getParentName() + "compIndex2 text"));
aComp.setMapItems(aCompMap);
aParent.setComponent(aComp);
return aParent;
}
//Demonstrates the error caused when a component property included in the main class table is null
public static Parent createComponentProblem1()
{
Parent aParent = new Parent();
aParent.setParentName("ParentCompProb1");
aParent.setSomeValue(50);
Component aComp = new Component();
//Because this is null, the component map will not be loaded back out
aComp.setCompName(null);
Map aCompMap = new HashMap(2);
aCompMap.put(aParent.getParentName() + "compIndex1", new MapItem(10, aParent.getParentName() + "compIndex1 text"));
aCompMap.put(aParent.getParentName() + "compIndex2", new MapItem(20, aParent.getParentName() + "compIndex2 text"));
aComp.setMapItems(aCompMap);
aParent.setComponent(aComp);
return aParent;
}
}
Parent.java Code:
package test.hibernate;
import java.util.Map;
public class Parent
{
private String parentName = "";
private int someValue = 0;
private int id = 0;
private Component component = null;
public Parent()
{
super();
}
public String getParentName()
{
return parentName;
}
public void setParentName(String parentName)
{
this.parentName = parentName;
}
public int getSomeValue()
{
return someValue;
}
public void setSomeValue(int someValue)
{
this.someValue = someValue;
}
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
public Component getComponent()
{
return component;
}
public void setComponent(Component component)
{
this.component = component;
}
}
Component.java Code:
package test.hibernate;
import java.util.Map;
public class Component
{
private String compName = "";
private Map mapItems = null;
public Component()
{
super();
}
public Map getMapItems()
{
return mapItems;
}
public void setMapItems(Map mapItems)
{
this.mapItems = mapItems;
}
/**
* If this is set to null, hibernate3 can not retrieve this class from the db
*/
public String getCompName()
{
return compName;
}
public void setCompName(String name)
{
this.compName = name;
}
}
MapItem.java Code:
package test.hibernate;
public class MapItem
{
private int number;
private String text;
public MapItem()
{
super();
}
public MapItem(int number, String text)
{
super();
this.number = number;
this.text = text;
}
public int getNumber()
{
return number;
}
public void setNumber(int number)
{
this.number = number;
}
public String getText()
{
return text;
}
public void setText(String text)
{
this.text = text;
}
}