-->
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.  [ 2 posts ] 
Author Message
 Post subject: EntityAsValueType mapping
PostPosted: Tue Oct 21, 2003 4:25 am 
Newbie

Joined: Tue Oct 21, 2003 3:41 am
Posts: 5
Location: Belgium
Hello,

Another idea I recently tried to implement (but failed because not enough knowledge/information available on Hibernate meta-data) :

Example : An application creates order information, but wants to be able to reference historical data efficiently. When related objects change, the order still has to have it's local copy of the object with the state at order time.

By this I mean that the columns of the related object are also available in the order table, and when we perform orderline.setProductType(prodTyp), all information of the object 'prodTyp' would get copied in columns of the orderline table.

This essentially means that we want to be able to have a certain Entity type (ProductType) and we sometimes whish to treat it as a ValueType in some other object. (I know you can serialize it in a BLOB column, but this is obviously less desirable for maintenance).

I tried to implement this idea as a UserType, but couldn't figure out where to get all the necessary metadata. (On a side note it would be great if the UserType could also know what the Type of the object it is mapping is)

I haven't finished it, but for completeness sake I'll include it :

package com.dhl.ncg.ums.model;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.apache.log4j.Logger;

import com.dhl.ncg.ums.aop.PersistencySupport;
import com.dhl.ncg.ums.exception.InternalServerException;

import net.sf.hibernate.HibernateException;
import net.sf.hibernate.SessionFactory;
import net.sf.hibernate.UserType;
import net.sf.hibernate.impl.SessionFactoryImpl;
import net.sf.hibernate.metadata.ClassMetadata;
import net.sf.hibernate.type.Type;

Code:
/**
* @author Dimitry D'hondt
*
* This class is the base class for all 'Entity as value' wrappers.
* Being able to wrap an AbstractEntity as a valkue inside of another object
* allows us to define 'historically copied data' in our domain model.
*
* A good example is the UldRepairPart object. This object needs to maintain
* an historical copy of UldPart, UlrPartCost, UldRepairLaboutCost and GenericHour objects,
* so that exact details are known about the cost-calculation, even if in the future
* any of the above objects are updated. Clearly updating a UldPart with a new number of minutes
* for labour does NOT affect repairs, made in the past..
*
* The containing object may declare a property with type = "SomeConcreteEntityAsValueUserType" and
* then all property columns for the value of that property will get copied into the containing object,
* when an assignment is made on the usertype property.
*
* No changes need to be made to the classes being included.
*
* AbstractEntities, wrapped as values, are not mutable either, you replace them completely, or not at all..
*
* Wrapping an entity as value also removes any relationships it may have with other entities.
* All relationships will simply be null.
*
* For a concrete example see UldRepairPart.
*/
public abstract class AbstractEntityAsValueUserType implements UserType {

   private static Logger log = Logger.getLogger(AbstractEntityAsValueUserType.class);

   /**
    * @see net.sf.hibernate.UserType#deepCopy(java.lang.Object)
    */
   public Object deepCopy(Object value) throws HibernateException {
      AbstractEntity abstractEntity = (AbstractEntity) value;
      return abstractEntity.clone();
   }

   /**
    * @see net.sf.hibernate.UserType#equals(java.lang.Object, java.lang.Object)
    */
   public boolean equals(Object x, Object y) throws HibernateException {
      AbstractEntity ae1 = (AbstractEntity) x;
      AbstractEntity ae2 = (AbstractEntity) y;
      return ae1.equals(ae2);
   }

   /**
    * @see net.sf.hibernate.UserType#isMutable()
    */
   public boolean isMutable() {
      return false;
   }

   /**
    * @see net.sf.hibernate.UserType#nullSafeGet(java.sql.ResultSet, java.lang.String[], java.lang.Object)
    */
   public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException {
      // TODO Auto-generated method stub
      return null;
   }

   /**
    * @see net.sf.hibernate.UserType#nullSafeSet(java.sql.PreparedStatement, java.lang.Object, int)
    */
   public void nullSafeSet(PreparedStatement st, Object value, int index) throws HibernateException, SQLException {
      // TODO Auto-generated method stub

   }

   /**
    * @see net.sf.hibernate.UserType#returnedClass()
    */
   public Class returnedClass() {
      // TODO Auto-generated method stub
      return null;
   }

   /**
    * @see net.sf.hibernate.UserType#sqlTypes()
    */
   public int[] sqlTypes() {
      ClassMetadata metaData = getClassMetadata();
      int[] ret = null;
      
      String[] properties = metaData.getPropertyNames();
      SessionFactoryImpl sessionFactory = (SessionFactoryImpl) PersistencySupport.getSessionFactory();
      Type[] types = metaData.getPropertyTypes();
      List sqlTypes = new ArrayList();
      for (int i = 0; i < types.length; i++) {
         Type type = types[i];
         String property = properties[i];
//         if(type.sqlTypes(sessionFactory).length != 1) {
////            types.add(r(type.sqlTypes(sessionFactory)[0]));
//         } else {
//            log.debug("Property <" + property + "> not mapped for EntityAsValue wrapper.");
//         }
      }
      
//      ret = (int[]) sqlTypes.toArray(new int[0]);

      return ret;      
   }

   /**
    * Override this operation to configure the metadata
    * @return
    */
   private ClassMetadata getClassMetadata() {
      ClassMetadata ret = null;
      
      try {
         Class clazz = Class.forName("com.dhl.ncg.ums.model." + getEntityClassName());
         ret = PersistencySupport.getSessionFactory().getClassMetadata(clazz);
      } catch(ClassNotFoundException e) {
         String msg = "Configuration for UserType <" + this.getClass().getName() + "> specified an entity class <" + getEntityClassName() + "> that is not available in the VM.";
         log.error(msg,e);
         throw new InternalServerException(msg);
      } catch(HibernateException e) {
         String msg = "Configuration for UserType <" + this.getClass().getName() + "> specified an entity class <" + getEntityClassName() + "> unknown to Hibernate.";
         log.error(msg,e);
         throw new InternalServerException(msg);
      }
      
      return ret;
   }
   
   /**
    * Override this operation to configure the concrete class to wrap.
    * Don't specify the package ! com.dhl.ncg.ums.model. is prefixed automatically.
    * @return
    */
   protected abstract String getEntityClassName();
}


Does anyone know how to pull this off ? Is this an idea for the next version of Hibernate ?

Kind regards,

Dimitry.

_________________
Dimitry D'hondt
IT Architect - Real Software n.v.
http://www.realsoftware.be

Author of 'Smile' an open-source JaveServer Faces implementation. (http://smile.sourceforge.net)


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 21, 2003 4:31 am 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
A good place for solutions/discussions like this is the Wiki community area. Code gets lost on the forum...

_________________
JAVA PERSISTENCE WITH HIBERNATE
http://jpwh.org
Get the book, training, and consulting for your Hibernate team.


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

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.