Hi,
I have two related simple class hierarchies with single table per class hierarchie strategy:
Payment (superclass), CreditcardPayment, MobilePayment
BasePrice (superclass), CreditcardPrice, MobilePrice
CreditCardPayment has an unidirectional one-to-many association with CreditCardPrice, and MobilePayment accordingly with MobilePrice.
Accessing a Payment e.g. with find() may result (it is not deterministic) in a WrongClassException when the associations are annotated for eager fetching (no problems with lazy fetching).
Quote:
org.hibernate.WrongClassException: Object with id: MP$2 was not of the specified subclass: de.mobileview.test.jpa.MobilePrice (loaded object was of wrong class class de.mobileview.test.jpa.CreditcardPrice)
The problem occured with hibernate 3.6 and 4.0.1.
Any help is appreciated.
Regards,
Gonne
Code:
@Entity
public abstract class Payment implements Serializable {
@Id private String id;
public Payment() {}
public Payment(String id) {
this.id = id;
}
}
@Entity
public class CreditcardPayment extends Payment implements Serializable {
private String ccnumber;
private String company;
@OneToMany(fetch=FetchType.EAGER, cascade=CascadeType.PERSIST)
public List<CreditcardPrice> prices = new ArrayList<>();
protected CreditcardPayment() {}
public CreditcardPayment(String id, String ccno, String company) {
super(id);
this.ccnumber = ccno;
this.company = company;
}
}
@Entity
public class MobilePayment extends Payment implements Serializable {
private String mobileAddress;
@OneToMany(fetch = FetchType.EAGER, cascade=CascadeType.PERSIST)
public List<MobilePrice> prices = new ArrayList<>();
protected MobilePayment() {}
public MobilePayment(String id, String mobileAdr) {
super(id);
this.mobileAddress = mobileAdr;
}
}
@Entity
public abstract class BasePrice implements Serializable {
@Id private String id;
protected int amount;
protected BasePrice() {}
protected BasePrice(String id, int amount) {
this.id = id;
this.amount = amount;
}
}
@Entity
public class CreditcardPrice extends BasePrice implements Serializable {
private String company;
protected CreditcardPrice() {}
public CreditcardPrice(String id, int amount, String company) {
super(id, amount);
this.company = company;
}
}
@Entity
public class MobilePrice extends BasePrice implements Serializable {
private String operator;
protected MobilePrice() {}
public MobilePrice(String id, int amount, String operator) {
super(id, amount);
this.operator = operator;
}
}
public class JpaMain {
private EntityManagerFactory emf;
private EntityManager em;
private EntityTransaction tx;
public JpaMain() {
emf = Persistence.createEntityManagerFactory("JpaTest");
em = emf.createEntityManager();
tx = em.getTransaction();
}
public void close() {
if (em != null) {
em.close();
}
emf.close();
}
private void create() {
tx.begin();
CreditcardPayment cc_pm;
CreditcardPrice cc_pr;
MobilePrice m_pr;
MobilePayment m_pm;
cc_pm = new CreditcardPayment("CC1", "54893423", "Machocard");
cc_pr = new CreditcardPrice("CC$1", 12, "Wiesacart");
cc_pm.prices.add(cc_pr);
cc_pr = new CreditcardPrice("CC$2", 12, "Döners Club");
cc_pm.prices.add(cc_pr);
em.persist(cc_pm);
m_pm = new MobilePayment("MP2", "+49171723737");
m_pr = new MobilePrice("MP$2", 81, "Vodafone");
m_pm.prices.add(m_pr);
em.persist(m_pm);
tx.commit();
}
private void query() {
em.clear(); // clear cache
Payment pm = em.find(Payment.class, "CC1"); // may result in WrongClassException
System.out.println(pm);
pm = em.find(Payment.class, "MP2"); // may result in WrongClassException
System.out.println(pm);
}
public static void main(String[] args) {
JpaMain main = new JpaMain();
try {
main.create();
main.query();
}
finally {
main.close();
}
}
}