2010-06-28 15 views
3

Quelqu'un a posé cette question sur les forums Hibernate et je la lie ici parce que j'ai la même question. Personne ne semblait être d'aucune aide là-bas alors j'espère que cela pourrait être plus utile.Utiliser Hibernate pour conserver une liste un-à-plusieurs avec un type de super-classe

Ici, il est:

Question on Hibernate forum

Merci.

+0

Qu'avez-vous essayé? Utiliser des annotations ou des mappages XML? –

+0

J'utilise des mappages XML comme ce type fait dans sa question. – NickDK

Répondre

2

Intéressant. Va ici ce que je l'ai fait

package br.com.ar.model.domain.Parent; 

@Entity 
public class Parent implements Serializable { 

    private Integer id; 

    private AbstractChild[] childArray; 

    @Id 
    @GeneratedValue 
    public Integer getId() { 
     return id; 
    } 

    public void setId(Integer id) { 
     this.id = id; 
    } 

    @OneToMany 
    @IndexColumn(name="CHILD_INDEX", nullable=false) 
    @JoinColumn(name="PARENT_ID", nullable=false) 
    @Cascade(CascadeType.SAVE_UPDATE) 
    public AbstractChild[] getChildArray() { 
     return childArray; 
    } 

    public void setChildArray(AbstractChild[] childArray) { 
     this.childArray = childArray; 
    } 

} 

Maintenant, notre gamme de AbstractChild (Etes-vous sûr que vous avez défini votre AbstractChild (Ici, il joue le rôle de la classe Livre) comme abstrait ???)

package br.com.ar.model.domain; 

@Entity 
/** 
    * I am using InheritanceType.SINGLE_TABLE instead of TABLE_PER_CLASS 
    * Because MySQL (DB used) DOES NOT SUPPORT identity generation strategy 
    * Otherwise, i will get some Exception 
    */ 
@Inheritance(strategy=InheritanceType.SINGLE_TABLE) 
@DiscriminatorColumn(
    name="BILLING_DETAILS_TYPE", 
    discriminatorType=DiscriminatorType.STRING 
) 
/** 
    * ARE YOU SURE your Book class HAS BEEN MARKED AS abstract 
    */ 
public abstract class AbstractChild implements Serializable { 

    private Integer id; 

    @Id 
    @GeneratedValue(strategy=GenerationType.AUTO) 
    public Integer getId() { 
     return id; 
    } 

    public void setId(Integer id) { 
     this.id = id; 
    } 

} 

mapping.hbm.xml (racine du classpath)

<hibernate-mapping> 
    <class name="br.com.ar.model.domain.AbstractChild" abstract="true"> 
    <id column="id" name="id" type="integer"> 
     <generator class="native"/> 
    </id> 
    <discriminator column="BILLING_DETAILS_TYPE" type="string"/> 
    <subclass name="br.com.ar.model.domain.Child" discriminator-value="CC"> 
     <property name="someProperty" type="string"/> 
    </subclass> 
    <!--I CAN NOT USE union-subclass because MySQL does not support DB identity generation strategy--> 
    <!--union-subclass name="br.com.ar.model.domain.Child"> 
     <property name="someProperty" type="string"/> 
    </union-subclass--> 
    </class> 
    <class name="br.com.ar.model.domain.Parent"> 
    <id column="id" name="id" type="integer"> 
     <generator class="native"/> 
    </id> 
    <array name="childArray" cascade="all"> 
     <key column="PARENT_ID"/> 
     <index column="SORT_ORDER"/> 
     <one-to-many class="br.com.ar.model.domain.AbstractChild"/> 
    </array> 
    </class> 
</hibernate-mapping> 

Testons maintenant

Avec

@Test 
public void doWithAnnotations() { 

    AnnotationConfiguration configuration = new AnnotationConfiguration(); 

    SessionFactory sessionFactory = configuration 

     .addAnnotatedClass(Parent.class) 
     .addAnnotatedClass(Child.class) 
     .addAnnotatedClass(AbstractChild.class) 
     .setProperty(Environment.DRIVER, "com.mysql.jdbc.Driver") 
     .setProperty(Environment.URL, "jdbc:mysql://127.0.0.1:3306/ar") 
     .setProperty(Environment.USER, "root") 
     .setProperty(Environment.PASS, "root") 
     .setProperty(Environment.SHOW_SQL, "true") 
     .setProperty(Environment.FORMAT_SQL, "true") 
     .setProperty(Environment.DIALECT, "org.hibernate.dialect.MySQLDialect") 
     .setProperty(Environment.HBM2DDL_AUTO, "create-drop").buildSessionFactory(); 

    Session session = sessionFactory.openSession(); 
    session.beginTransaction(); 

    Parent parent = new Parent(); 
    parent.setChildArray(new AbstractChild[] {new Child("AAA"), new Child("BBB")}); 

    session.save(parent); 

    session.getTransaction().commit(); 
    session.close(); 
} 

Et sans

@Test 
public void doWithoutAnnotations() { 

    Configuration configuration = new Configuration().configure(); 

    SessionFactory sessionFactory = configuration.buildSessionFactory(); 

    Session session = sessionFactory.openSession(); 
    session.beginTransaction(); 

    Parent parent = new Parent(); 
    parent.setChildArray(new AbstractChild[] {new Child("AAA"), new Child("BBB")}); 

    session.save(parent); 

    session.getTransaction().commit(); 
    session.close(); 
} 

Les deux fonctionnent très bien!

+0

Vous avez raison. Le problème est que vous ne pouvez pas avoir une liste de superclasses si vous utilisez la stratégie de mappage de table par classe concrète. Cette table par hiérarchie fonctionne pour ce problème. Merci. – NickDK