Search code examples
jpaobjectdb

JPA inheritance issue with ObjectDB - Field not found in type error


I'm using ObjectDB as my JPA provider, and I'm facing an issue with inheritance. My classes are as follows:

@Entity
public class Item implements Serializable, Comparable<Item> {
    boolean retired;
    // other fields, getters, and setters
}

@Entity
@Inheritance
public class PharmaceuticalItem extends Item implements Serializable {
    // ...
}

@Entity
@Inheritance
public class Vtm extends PharmaceuticalItem implements Serializable {
    // ...
}

I have a JPQL query that looks like this:

String jpql = "Select vtm "
            + " from Vtm vtm "
            + " where vtm.retired=:ret "
            + " order by vtm.name";

When I try to run this query, I get the following error:

Error executing query: Field 'retired' is not found in type 'com.divudi.entity.pharmacy.Vtm'

The same code works fine with MySQL and EclipseLink, but not with ObjectDB. I've also tried using the @MappedSuperclass annotation instead of the @Inheritance annotation, but the issue persists.

@MappedSuperclass
public class Item implements Serializable, Comparable<Item> {
    // ...
}

@MappedSuperclass
public class PharmaceuticalItem extends Item implements Serializable {
    // ...
}

@Entity
public class Vtm extends PharmaceuticalItem implements Serializable {
    // ...
}

Does anyone have any idea how to resolve this issue with ObjectDB?

Thanks in advance!

This is the method in abstract facade.

public List<T> findByJpql(String temSQL, Map<String, Object> parameters) {
    System.out.println("findByJpql");
    System.out.println("JPQL: " + temSQL);
    System.out.println("Parameters: " + parameters);
    
    TypedQuery<T> qry = getEntityManager().createQuery(temSQL, entityClass);
    Set s = parameters.entrySet();
    Iterator it = s.iterator();
    while (it.hasNext()) {
        Map.Entry m = (Map.Entry) it.next();
        String pPara = (String) m.getKey();
        if (m.getValue() instanceof Date) {
            Date pVal = (Date) m.getValue();
            qry.setParameter(pPara, pVal, TemporalType.DATE);
        } else {
            Object pVal = (Object) m.getValue();
            qry.setParameter(pPara, pVal);
        }
    }
    
    List<T> ts;
    try {
        ts = qry.getResultList();
        System.out.println("Results found: " + ts.size());
    } catch (Exception e) {
        System.out.println("Error executing query: " + e.getMessage());
        ts = new ArrayList<>();
    }
    
    return ts;
}

This is the method in the controller.

public String navigateToListAllVtms() {
    System.out.println("navigateToListAllVtms");
    String jpql = "Select vtm "
            + " from Vtm vtm "
            + " where vtm.retired=:ret "
            + " order by vtm.name";
    System.out.println("JPQL: " + jpql);

    Map<String, Object> m = new HashMap<>();
    m.put("ret", false);
    System.out.println("Parameters: " + m);

    items = getFacade().findByJpql(jpql, m);
    
    if (items == null) {
        System.out.println("Items list is null");
    } else {
        System.out.println("Items list size: " + items.size());
        for (Vtm item : items) {
            System.out.println("Vtm: " + item);
        }
    }

    return "/emr/reports/vtms?faces-redirect=true";
}

Solution

  • From the docs for @Inheritance

    Defines the inheritance strategy to be used for an entity class hierarchy. It is specified on the entity class that is the root of the entity class hierarchy. If the Inheritance annotation is not specified or if no inheritance type is specified for an entity class hierarchy, the SINGLE_TABLE mapping strategy is used.

    You annotated your sub-classes with @Inheritance which is the opposite of what the doc says. Hence the following changes should work.

    @Entity
    @Inheritance // added
    public class Item ...
    
    @Entity
    // removed @Inheritance 
    public class PharmaceuticalItem extends Item ...
    
    @Entity
    // removed @Inheritance 
    public class Vtm extends PharmaceuticalItem ...