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: JPA: SINGLE_TABLE Inheritance, no discriminator in SQL
PostPosted: Fri Dec 21, 2007 11:19 am 
Newbie

Joined: Thu Dec 20, 2007 11:25 am
Posts: 1
Hello,

environment:
i use container managed jta transactions (glassfish v2, EJB 3.0) and i use only jpa, i.e.
my whole application is container managed.

model
My model consits of two tables, a contracts table and a contract_data table.
The contract table is mapped to ContractSuperClass and the contract_data
table is mapped to ContractDataSuperClass.

inheritance
I use SINGLE_TABLE inheritance in both tables.
I can't change the db schema.

ContractSuperClass has two subclasses Contract and SpecialContract.
ContractDataSuperClass hast two subclasses ContractData and SpecialContractReference.

mappings
Contract has two OneToMany bi-directional mappings to ContractData
and SpecialContractReference. SpecialContract has one OneToMany bi-directional mapping to ContractData.
A SpecialContractReference has a uni-directional ManyToOne mapping to a SpecialContract.
Image

problem
Every time i try to get all the ContractData the sql-statements generated
don't contain the discriminator, so i end up with a mixture of data representing
ContractData and SpecialContractReferences, both mapped to ContractData.
If i subsequently try to get all the SpecialContractReferences i get a LazyInitException.

The strang thing is that the sql statement generated to retrive the Contract
has a where clause *with* the discriminator column, whereas all subsequent statements
don't have the discriminator column in the where clause.

using an other persistence provider
If i change the persistence provider in the persistence.xml file, i.e.
i substitute
<provider>org.hibernate.ejb.HibernatePersistence</provider>
with
<provider>oracle.toplink.essentials.PersistenceProvider</provider>

everything works fine and i get the desired distinction between
ContractData and SpecialContractReferences. The generated sql statements now
contain the discriminator column in the where clause.

back to Hibernate
But since i like Hibernate and i don't want to switch to toplink essentials,
i would highly appreaciate some advice as how to fix this problem.



Hibernate version:
Hibernate Core 3.2.5.ga (31.07.2007)
Hibernate Annotations 3.3.0 GA (20.03.2007)
Hibernate EntityManager 3.3.1 GA (29.03.2007)
Mapping documents:

Code:
@Entity
@Table(name="CONTRACTS")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="DISCRIMINATOR", discriminatorType=DiscriminatorType.CHAR)
public class ContractSuperClass implements Serializable {
   private static final long serialVersionUID = 1L;
   public ContractSuperClass() {}

   @Id @Column(name="ID")
   private Integer id;
   
   @Column(name="DATA")
   private String data;

   // getter and setter ...
}


@Entity
@Table(name="CONTRACT_DATA")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="DISCRIMINATOR", discriminatorType=DiscriminatorType.CHAR)
public class ContractDataSuperClass implements Serializable {
   private static final long serialVersionUID = 1L;
   public ContractDataSuperClass() {}
   
        @EmbeddedId private ContractDataPK contractDataPK;
   
   @Column(name = "DATA")
        private String data;
   
   // getter and setter ...
}

@Entity
@DiscriminatorValue(value="C")
public class Contract extends ContractSuperClass implements Serializable {
   private static final long serialVersionUID = 1L;
   public Contract() {}
   
   @OneToMany(mappedBy="contract")
   private Collection<ContractData> contractData;
   
   @OneToMany(mappedBy="contract")
   private Collection<SpecialContractReference> specialContractReferences;

   // getter and setter ...
}

@Entity
@DiscriminatorValue(value="S")
public class SpecialContract extends ContractSuperClass implements Serializable {
   private static final long serialVersionUID = 1L;
   
    public SpecialContract () {
    }

   @OneToMany(mappedBy="contract", fetch=FetchType.EAGER)
   private Collection<ContractData> contractData;

   // getter and setter ...
}

@Entity
@DiscriminatorValue(value="D")
public class ContractData extends ContractDataSuperClass implements Serializable {
   private static final long serialVersionUID = 1L;

   public ContractData() {}
   
   @ManyToOne()
   @JoinColumn(name="ID", referencedColumnName="ID", insertable=false, updatable=false)
   private ContractSuperClass contract;
   
   // getter and setter ...
}

@Entity
@DiscriminatorValue(value="R")
public class SpecialContractReference extends ContractDataSuperClass implements Serializable {
   private static final long serialVersionUID = 1L;
   
   public SpecialContractReference() {}
   
   @ManyToOne()
   @JoinColumn(name="ID", insertable=false, updatable=false)
   private ContractSuperClass contract;
   
   @ManyToOne(fetch=FetchType.LAZY)
   @JoinColumn(name="ID_SPECIAL", referencedColumnName="ID", insertable=false, updatable=false)
   private SpecialContract specialContract;

   // getter and setter ...
}

Code between sessionFactory.openSession() and session.close():
Code:
@Stateless
public class ContractFacade {
   @PersistenceContext
   private EntityManager em;
   
   public String getTheStuffDone() {
      
      String result = "";
      
      Contract contract = em.find(Contract.class, 1);
      
      // here it happens ...
      Collection<ContractData> data = contract.getContractData();
      
      for (ContractData d : data) {
         result += d.getData();
      }
      
      // result now contains data from instances of ContractData, but it also contains data which belongs to
      // SpecialContractReference instances
      
      // ... and here some other strange stuff happens
                // the persistenceBag doesn't contain any data
                // even with FetchType.EAGER
      Collection<SpecialContractReference> specialContractRefs = contract.getSpecialContractReferences();
      
      // here i get a LazyInitException
      for (SpecialContract s : specialContractRefs) {
         result += s.getData();
      }
      
      return result;
   }
   
   // other stuff ...
}


Name and version of the database you are using:
IBM DB2 UDB Version 9


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.