简体   繁体   中英

Single table inheritance strategy (or table per class hierarchy) with Oracle and Hibernate

I'm using JEE6, Oracle database 11g and Hibernate. I'm trying to make the following inheritance work :

在此处输入图片说明

So WikiNotification and TodoNotification extend Notification. According to the single table inheritance strategy, there will be one and one only table for those three classes in the database.

Here is Notification :

@Entity
@ForceDiscriminator
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="NOTIFICATION_TYPE")
@Table(name="SMH_NOTIFICATION")
public class Notification extends AbstractPersistentObject{

    /**
     * 
     */
    private static final long serialVersionUID = -2313098389774322743L;

    @ManyToOne
    @JoinColumn(name="RECEIVER_ID", nullable=false)
    private Userprofile receiver;


    @Column(name="CLASSIFICATION",nullable = true, length=30)
    private String classification;

    @Column(name="DESCRIPTION", nullable = true, length=60)
    private String description;

    @Column(name="DEADLINE")
    @Temporal(TemporalType.DATE)
    private Date deadline;

This is WikiNotification :

//@Entity
@DiscriminatorValue("Wiki")
//@Table(name="SMH_NOTIFICATION")
//@Inheritance(discriminatorValue="Wiki")
public class WikiNotification extends Notification{

    /**
     * 
     */
    private static final long serialVersionUID = 5025643991898983953L;


    //the sender is the user who triggers the notification
    //for example, it can the one who modifies someone else's chapters
    @ManyToOne
    @JoinColumn(name="SENDER_ID", nullable=false)
    private Userprofile sender;

    //"0" if the owner has not accepted yet, "1" if he accepted
    @Column(name="ACCEPTED", length=1, nullable=false)
    private String accepted;

    //the notification type can be "delete", "submit" or "modify"
    @Column(name="NOTIFICATIONTYPE",length=20,nullable=false)
    private String notificationType;

    //mofications, deletions and submissions are related to this article chapter
    @ManyToOne
    @JoinColumn(name="ARTICLECHAPTER",nullable=false)
    private ArticleChapter chapter;

And TodoNotification :

//@Entity
@DiscriminatorValue("Todo")
//@Table(name="SMH_NOTIFICATION")
public class TodoNotification extends Notification{

    /**
     * 
     */
    private static final long serialVersionUID = 2482841237595539431L;

    @OneToOne
    @JoinColumn(name="TODO_ID", nullable=false)
    private ToDo todo;

What is not working so far is :

  • I have one table 'SMH_NOTIFICATION' created but I don't see the discriminator column 'NOTIFICATION_TYPE' and I don't have the other columns for WikiNotification and TodoNotification :

在此处输入图片说明

  • when I write @Entity in the classes WikiNotification and TodoNotification, I have two tables Wikinotification and Todonotification created in my database, which is not what I expected. There should be only one table 'SMH_NOTIFICATION'

I tried the following tutorials but it hasn't worked yet :

http://www.dineshonjava.com/p/implementing-inheritance-in-hibernate.html#.Vd71ZiXtlHw

https://en.wikibooks.org/wiki/Java_Persistence/Inheritance

http://www.thejavageek.com/2014/05/14/jpa-single-table-inheritance-example/

http://uaihebert.com/jpa-mini-book-first-steps-and-detailed-concepts/13/

http://viralpatel.net/blogs/hibernate-inheritence-table-per-hierarchy-mapping/

Edit:

When I make Notification an abstract class and when I add @Entity in WikiNotification and TodoNotification I get the following lines in Eclipse :

    INFO  27.08.15 14:45:34.996  org.hibernate.tool.hbm2ddl.DatabaseMetadata@getTableMetadata: table not found: TodoNotification
    INFO  27.08.15 14:45:35.001  org.hibernate.tool.hbm2ddl.DatabaseMetadata@getTableMetadata: table not found: WikiNotification
    INFO  27.08.15 14:45:35.007  org.hibernate.tool.hbm2ddl.DatabaseMetadata@getTableMetadata: table not found: TodoNotification
    INFO  27.08.15 14:45:35.012  org.hibernate.tool.hbm2ddl.DatabaseMetadata@getTableMetadata: table not found: WikiNotification

So I have two tables in my database, WikiNotification and TodoNotification, whereas I only expect one table because of the single table inheritance strategy.

    <hibernate-configuration>
 <session-factory>
        <property name="hibernate.show_sql">false</property>
        <property name="hibernate.format_sql">false</property>
        <property name="hibernate.bytecode.use_reflection_optimizer">false</property>
        <!--  
        <property name="current_session_context_class">thread</property>
        -->
        <property name="hibernate.hbm2ddl.auto">update</property>

       <!-- 
        <property name="hibernate.show_sql">true</property>
        <property name="hibernate.format_sql">true</property>
        <property name="hibernate.use_sql_comments">true</property>
         -->
 </session-factory>
</hibernate-configuration>

DAO configuration file:

<tx:annotation-driven transaction-manager="transactionManager" />

<bean id="transactionManager"
    class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory">
        <ref local="sessionFactory" />
    </property>
</bean>

<bean id="sessionFactory"
    class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="hibernateProperties">
        <props>
            <!-- Hibernate dialect can be defined in application context -->
            <prop key="hibernate.dialect">%{smh.hibernate.dialect}</prop>
            <prop key="hibernate.show_sql">false</prop> 
            <prop key="hibernate.hbm2ddl.auto">update</prop> 
            <prop key="hibernate.connection.SetBigStringTryClob">true</prop>
            <prop key="hibernate.jdbc.batch_size">0</prop>
        </props>
    </property>
    <property name="dataSource" ref="dataSource" />
    <property name="packagesToScan">
        <list>
            <value>com.smh.core.domain</value>
            <!--
                <value>com.seti.core.domain.entity.task.Task</value>
            -->
        </list>
    </property>
</bean>
<bean id="multipartResolver"
    class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

    <!-- one of the properties available; the maximum file size in bytes -->
    <property name="maxUploadSize" value="50000000" />
</bean>

<bean id="persistenceExceptionTranslationPostProcessor"  


class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />

Notification should be abstract . TodoNotification & WikiNotification should have the @Entity annotation.

There are couple of things you need to do:

  1. Make sure whatever dialect you are using is correct as per your Oracle Version.
  2. You need to add @Entity on all three classes.
  3. You need to provide mapping of all classes into your hibermate.cfg file
  4. You need to remove "nullable=false" from the sub-classes, because "TODO_ID" will be null when Discriminator.Value= "Wiki" and WikiNotification member values will be Discriminator.Value= "Todo" .
  5. As a try, instead of setting hibernate.hbm2ddl.auto to update , try setting it to " create " and then check the result.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM