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.
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