-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 
Author Message
 Post subject: Map<Integer, List<Object>> mapping - how to?
PostPosted: Tue Oct 26, 2010 2:05 pm 
Newbie

Joined: Mon Oct 18, 2010 9:35 am
Posts: 10
Hi to all,

I have a case where I need to map property that looks like this:
Code:
private Map<Integer, List<Size>> colorSizesMap = new HashMap<Integer, List<Size>>();

I was searching through the forum and there are a lot of unanswered posts of this type, except one where they forward to this url. Now, the case there is for two tables with a many-to-many association. I have a ternary association that is described by the following DB design:
Image
The Map property colorSizesMap resides in Product.java and the key is the colorId, the value is a List of Sizes. The list of Sizes belongs to each color for the appropriate product/productId.

I tried mapping the colorSizesMap property like in the xebia blog, so instead of that Map I created a similar property in the Product class:
Code:
private Map<Integer, ColorSizesEntity> colorSizesMapTest = new HashMap<Integer, ColorSizesEntity>();

And the ColorSizesEntity.java:
Code:
public class ColorSizesEntity implements Serializable {

   private long id;
   private List<Size> sizes;

   public ColorSizesEntity() {
      super();
      sizes = new ArrayList<Size>();
   }
   //setters, getters
}

The mapping I used (see the <map> element and the <class name="ColorSizesEntity"> element):
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="product">

   <class name="Product" table="Product" lazy="false">
      <id name="id" column="id">
         <generator class="native" />
      </id>
      <map name="colorSizesMapTest" table="DetailedProduct"> <!--  -->
         <key column="personId"/>
         <map-key column="colorId" type="integer" />
         <one-to-many class="ColorSizesEntity" />
      </map>
   </class>
   <class name="ColorSizesEntity" table="DetailedProduct" lazy="false">
      <id name="id" column="colorId">
         <generator class="native" />
      </id>
      <list name="sizes">
         <key column="sizeId"/>
           <index column="pos"/>
           <one-to-many class="Size"/>
       </list>
   </class>
   
</hibernate-mapping>

No error was shown when hibernate maps/configures the mapping files, but when I try to load a Product, the id is there, but there is no Map property (it is null). Why don't I see it?

If you want to try this example, I give you all the classes, mapping and configuration files below.
Database DDL:
Code:
CREATE TABLE Product (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(200) NOT NULL,
  PRIMARY KEY  (`id`),
) TYPE=InnoDB AUTO_INCREMENT=0 ;

CREATE TABLE Size (
  `id` int(4) NOT NULL auto_increment,
  `nameSize` varchar(20) NOT NULL,
  `pos` int NOT NULL,
  PRIMARY KEY (`id`)
) TYPE=InnoDB AUTO_INCREMENT=0;

CREATE TABLE Color (
  `id` int(4) NOT NULL auto_increment,
  `name` varchar(20) NOT NULL,
  PRIMARY KEY (`id`)
) TYPE=InnoDB AUTO_INCREMENT=0;

CREATE TABLE DetailedProduct (
  `productId` int(11) NOT NULL,
  `sizeId` int(4) NOT NULL,
  `colorId` int(4) NOT NULL,
  `quantity` int NOT NULL,
  PRIMARY KEY (productId,sizeId,colorId),
  FOREIGN KEY (productId)
   REFERENCES Product(id)
   ON UPDATE CASCADE ON DELETE CASCADE,
  FOREIGN KEY (sizeId)
   REFERENCES Size(id)
   ON UPDATE CASCADE ON DELETE RESTRICT,
  FOREIGN KEY (colorId)
   REFERENCES Color(id)
   ON UPDATE CASCADE ON DELETE RESTRICT
) TYPE=InnoDB AUTO_INCREMENT=0 ;

INSERT INTO Size (nameSize, pos) VALUES ("0m",0),("6m",1),("2y",2),("4y",3);
INSERT INTO Color (name) VALUES ("yellow"),("green"),("red"),("blue"),("black"),("white"),("pink");
INSERT INTO PRODUCT (name) VALUES ("p1"),("p2"),("p3");
INSERT INTO DetailedProduct (productId,sizeId,colorId,quantity)
VALUES (1,1,1,55),(1,1,2,7),(1,1,3,1),(1,2,1,125),(1,2,3,123),(2,2,1,1200),(2,2,3,1000),(2,4,1,100),(2,4,2,9),(2,4,4,11),(3,1,1,16),(3,1,2,15),(3,1,3,14),(3,3,2,23),(3,3,3,21);

classes:
Code:
public class Color implements Serializable, Comparable<Color>{
   private int id;
   private String name;
   //setters getters constructor
}
public class Size implements Serializable, Comparable<Size>{
   private int id;
   private String name;
   private int pos;
   //setters getters constructor   
}
public class DetailedProduct implements Serializable, Comparable<DetailedProduct> {
   private DetailedProductPK detailedProductPK;
   private Product product;
   private int quantity;
   //setters getters constructor
}
public class DetailedProductPK implements Serializable, Comparable<DetailedProductPK> {
   private long productId;
   private long sizeId;
   private long colorId;
   //setters getters constructor
}
public class Product implements Comparable<Product>, Serializable {
   private long id;
   private Map<Integer, ColorSizesEntity> colorSizesMapTest = new HashMap<Integer, ColorSizesEntity>();
   //setters getters constructor   
}

mapping files:
Code:
<hibernate-mapping package="product">
   <class name="Color" table="Color" lazy="false">
      <id name="id" column="id">
         <generator class="native" />
      </id>
      <property name="name" type="string" column="name" />
   </class>
</hibernate-mapping>
<hibernate-mapping package="product">

   <class name="Product" table="Product" lazy="false">
      <id name="id" column="id">
         <generator class="native" />
      </id>
      <map name="colorSizesMapTest" table="DetailedProduct"> <!--  -->
         <key column="personId"/>
         <map-key column="colorId" type="integer" />
         <one-to-many class="ColorSizesEntity" />
      </map>
   </class>
   <class name="ColorSizesEntity" table="DetailedProduct" lazy="false">
      <id name="id" column="colorId">
         <generator class="native" />
      </id>
      <list name="sizes">
         <key column="sizeId"/>
           <index column="pos"/>
           <one-to-many class="Size"/>
       </list>
   </class>
   
</hibernate-mapping>
<hibernate-mapping package="product" >
   <class name="DetailedProduct" table="DetailedProduct" lazy="false">
      <composite-id name="detailedProductPK" class="DetailedProductPK">
         <key-many-to-one name="productId" class="Product" column="productId"/>
         <key-many-to-one name="sizeId" class="Size" column="sizeId"/>
         <key-many-to-one name="colorId" class="Color" column="colorId"/>
      </composite-id>
      <many-to-one name="product" class="Product" column="productId"
            insert="false" update="false"/>
      <property name="quantity" type="integer" not-null="true" column="quantity"/>
   </class>

</hibernate-mapping>
<hibernate-mapping package="product">
   <class name="Size" table="Size" lazy="false">
      <id name="id" column="id">
         <generator class="native" />
      </id>
      <property name="name" type="string" column="name" />
      <property name="pos" type="integer" column="pos" />
   </class>
</hibernate-mapping>

HibernateUtil:
Code:
public class HibernateUtil {
   private static final SessionFactory sessionFactory;
   static {
      try {
         // Create the SessionFactory from hibernate.cfg.xml
         sessionFactory = new Configuration().configure()
               .buildSessionFactory();
      } catch (Throwable ex) {
         // Make sure you log the exception, as it might be swallowed
         System.err.println("Initial SessionFactory creation failed." + ex);
         throw new ExceptionInInitializerError(ex);
      }
   }
   public static SessionFactory getSessionFactory() {
      return sessionFactory;
   }
}

hibernate.cfg.xml:
Code:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
   <session-factory>
      <!-- Database connection settings -->
      <property name="connection.driver_class">org.gjt.mm.mysql.Driver</property>
      <property name="connection.url">jdbc:mysql://hostName/dbName</property>
      <property name="connection.username">rootUsername</property>
      <property name="connection.password">rootPassword</property>
      <!-- JDBC connection pool (use the built-in) -->
      <property name="connection.pool_size">1</property>
      <!-- SQL dialect -->
      <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
      <!-- Enable Hibernate's automatic session context management -->
      <property name="current_session_context_class">thread</property>
      <!-- Disable the second-level cache -->
      <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
      <!-- Echo all executed SQL to stdout -->
      <property name="show_sql">true</property>
      <property name="hibernate.c3p0.min_size">2</property>
          <property name="hibernate.c3p0.max_size">20</property>
          <property name="hibernate.c3p0.timeout">300</property>
          <property name="hibernate.c3p0.max_statements">50</property>
          <property name="hibernate.c3p0.idle_test_period">3000</property>
      <mapping resource="product/Size.hbm.xml"/>
      <mapping resource="product/Color.hbm.xml"/>
      <mapping resource="product/DetailedProduct.hbm.xml"/>
      <mapping resource="product/Product.hbm.xml"/>
   </session-factory>
</hibernate-configuration>

The start class (main) MapListMappingBehaviourMain.java:
Code:
public class MapListMappingBehaviourMain {

   public static void main(String[] args) {
      MapListMappingBehaviourMain mgr = new MapListMappingBehaviourMain();
      // save some elements
      Product product = (Product)mgr.getObject((long)4, Product.class);
      List<Object> products = new ArrayList<Object>();
      products.add(product);
      printObjects(products);
      HibernateUtil.getSessionFactory().close();
   }
   private static void printObjects(List<Object> objects) {
      for (int i = 0; i < objects.size(); i++) {
         Object object = objects.get(i);
         if (object instanceof Product) {
            System.out.println("Product: " + ((Product) object).getId());
         }
      }
   }
   private Object getObject(long objectId, Class clazz) {
      Session session = HibernateUtil.getSessionFactory().getCurrentSession();
      session.beginTransaction();
//      Object object = session.load(clazz, new Long(objectId));
      Object object = session.get(clazz, new Long(objectId));
      session.getTransaction().commit();
      return object;
   }
}


I can get the needed results with the following query:
Code:
SELECT dp.productId, dp.colorId, dp.sizeId, s.nameSize
FROM DetailedProduct dp
JOIN Size s
ON s.id = dp.sizeId
WHERE dp.productId = 2
ORDER BY dp.colorId, dp.productId, dp.sizeId;

or if you prefer no JOIN:
Code:
SELECT dp.productId, dp.colorId, size.id, size.nameSize
FROM DetailedProduct dp, Size size
WHERE dp.productId=2 AND dp.sizeId=size.id
ORDER BY dp.colorId, dp.productId, dp.sizeId;


Any help would be appreciated! Maybe there is no way of mapping this property like this. I really tried a bunch of stuff but nothing worked. Perhaps I should turn to the <join> element and try something with it. Anyways, whatever lies on your mind, please send it here!

Kind Regards,
Despot


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.