Hi feh
I've implemented your example scenario using table-per-subclass to create a separate table for A, B and C. 
I couldn't get this working using the D interface alone - added an abstract class 'DImpl' that implements D and is extended by concrete classes B and C. There are private (hibernate only) get/set methods for the DImpl in A and public get/set methods for DReference.
The test case creates 2 instances of A in the database - one with A as the DRef, one with B as the DRef. When the A's are re-loaded from the DB I print the class names of the DRef. As expected they are A and B;)
My HibernateUtil is configured to use hsqldb.
Mike
class A
Code:
package test.feh;
public class A {
   private Long id;
   private DImpl dImpl;
   
   public Long getId() {
      return id;
   }
   public void setId(Long id) {
      this.id = id;
   }
   public D getDReference() {
      return dImpl;
   }
   public void setDReference(D dReference) {
      if (!(dReference instanceof DImpl)) {
         throw new IllegalArgumentException("DReference must be an instance of class DImpl");
      }
      dReference = (DImpl)dReference;
   }
   
   @SuppressWarnings("unused")
   private DImpl getDImpl() {
      return dImpl;
   }
   @SuppressWarnings("unused")
   private void setDImpl(DImpl impl) {
      dImpl = impl;
   }
}
class B
Code:
package test.feh;
public class B extends DImpl {
}
class C
Code:
package test.feh;
public class C extends DImpl {
}
interface D
Code:
package test.feh;
public interface D {
}
abstract class DImpl
Code:
package test.feh;
public abstract class DImpl implements D {
   private Long id;
   private A aReference;
   public Long getId() {
      return id;
   }
   public void setId(Long id) {
      this.id = id;
   }
   public A getAReference() {
      return aReference;
   }
   public void setAReference(A reference) {
      aReference = reference;
   }
}
class HibernateUtil
Code:
package test.feh;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtil {
    private static SessionFactory factory;
    static {
       Configuration config = new Configuration()
          .addClass(A.class)
          .addClass(DImpl.class)
          .setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect")
         .setProperty("hibernate.connection.driver_class", "org.hsqldb.jdbcDriver")
         .setProperty("hibernate.connection.url", "jdbc:hsqldb:mem:test")
          .setProperty("hibernate.connection.username", "sa")
          .setProperty("hibernate.connection.password", "")
          .setProperty("hibernate.hbm2ddl.auto", "create-drop")
         .setProperty("hibernate.cache.provider_class", "org.hibernate.cache.NoCacheProvider")
         .setProperty("hibernate.show_sql", "true");
        HibernateUtil.setSessionFactory(config.buildSessionFactory());
    }
    public static synchronized Session getSession() {
        if (factory == null) {
            factory = new Configuration().configure().buildSessionFactory();
        }
        return factory.openSession();
    }
    public static void setSessionFactory(SessionFactory factory) {
        HibernateUtil.factory = factory;
    }
}
class TestIt
Code:
package test.feh;
import junit.framework.TestCase;
import org.hibernate.Hibernate;
import org.hibernate.Session;
public class TestIt extends TestCase {
   public void testLoad() {
      Long aWithBId = createDatabaseObjects(new B());
      Long aWithCId = createDatabaseObjects(new C());
      Session session = HibernateUtil.getSession();
      A aWithB = (A)session.load(A.class, aWithBId);
      A aWithC = (A)session.load(A.class, aWithCId);
      Hibernate.initialize(aWithB);
      Hibernate.initialize(aWithC);
      session.close();
      
      System.out.println("A with B - DReference class = "+aWithB.getDReference().getClass());
      System.out.println("A->B->A.id: "+aWithB.getDReference().getAReference().getId());
      System.out.println("A with C - DReference class = "+aWithC.getDReference().getClass());
      System.out.println("A->C->A.id: "+aWithC.getDReference().getAReference().getId());
   }
   private Long createDatabaseObjects(D d) {
      Session session = HibernateUtil.getSession();
      session.beginTransaction();
      
      session.save(d);
      A a = new A();
      a.setDReference(d);
      Long aId = (Long)session.save(a);
      
      session.getTransaction().commit();
      session.close();
      return aId;
   }
   
}
Mapping File A.hbm.xml
Code:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
  "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="test.feh">
 
<class name="A" table="a_table"> 
   <id name="id" column="id"> 
      <generator class="increment"/> 
   </id> 
   <one-to-one name="DImpl"/>
    
</class>
 
</hibernate-mapping> 
Mapping File DImpl.hbm.xml
Code:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
  "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="test.feh">
<class name="DImpl" table="d_table">
    <id name="id" column="id">
        <generator class="native"/>
    </id>
    <one-to-one name="AReference"/>
    
    <joined-subclass name="B" table="b_table">
        <key column="id"/>
    </joined-subclass>
    <joined-subclass name="C" table="c_table">
        <key column="id"/>
    </joined-subclass>
</class>
</hibernate-mapping>