Hello.
I've built a test project to evaluate inheritance impacts on JPA/Hibernate persistence.
The java classes at the end of the post give the detailed code.
In the hierarchy, the intermediate abstract entity "device" has a many-to-one association with the entity "brand". It seems that the lazy resolution of the a brand's devices leads to a bad generated SQL query, finding on the device table an attribute of the super class "thing".
Here is the generated request, with the bad column "kind_of_thing" wich is actually a super class table field.
Code:
    select
        devices0_.brand_code as brand_co3_0_0_,
        devices0_.identifier as identifi2_2_0_,
        devices0_.identifier as identifi2_5_1_,
        devices0_1_.description as descript3_5_1_,
        devices0_1_.person_identifier as person_i4_5_1_,
        devices0_.brand_code as brand_co3_2_1_,
        devices0_.model as model1_2_1_,
        devices0_2_.bearer as bearer1_4_1_,
        devices0_3_.cpu as cpu1_1_1_,
        devices0_.[b][color=#FF0000]kind_of_thing[/color][/b] as kind_of_1_5_1_ 
    from
        Device devices0_ 
    inner join
        Thing devices0_1_ 
            on devices0_.identifier=devices0_1_.identifier 
    left outer join
        Phone devices0_2_ 
            on devices0_.identifier=devices0_2_.identifier 
    left outer join
        Computer devices0_3_ 
            on devices0_.identifier=devices0_3_.identifier 
    where
        devices0_.brand_code=?
I've done tests with versions 4.3.8.Final, 4.3.10.Final, and 5.0.0.CR1, and the result is the same...
Is there anything wrong in my code, or is it a probable bug ?
Thanks for your help.
Regards.
Code:
package my.tests.jpa.entities;
import javax.persistence.Basic;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "kind_of_thing")
public abstract class Thing {
   @Id
   private Integer identifier;
   @Basic
   private String description;
   @ManyToOne(fetch = FetchType.LAZY)
   @JoinColumn(name = "person_identifier")
   private Person owner;
   public Integer getIdentifier() {
      return identifier;
   }
   public void setIdentifier(final Integer identifier) {
      this.identifier = identifier;
   }
   public String getDescription() {
      return description;
   }
   public void setDescription(final String description) {
      this.description = description;
   }
   public Person getOwner() {
      return owner;
   }
   public void setOwner(final Person owner) {
      this.owner = owner;
   }
   @Override
   public String toString() {
      return getClass().getSimpleName() + "[identifier=" + identifier + ", description=" + description + "]";
   }
}
Code:
package my.tests.jpa.entities;
import javax.persistence.Basic;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.PrimaryKeyJoinColumn;
@Entity
@PrimaryKeyJoinColumn(name = "identifier")
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Device extends Thing {
   @Basic
   private String model;
   @ManyToOne(fetch = FetchType.LAZY)
   @JoinColumn(name = "brand_code")
   private Brand brand;
   public String getModel() {
      return model;
   }
   public void setModel(final String model) {
      this.model = model;
   }
   public Brand getBrand() {
      return brand;
   }
   public void setBrand(final Brand brand) {
      this.brand = brand;
   }
   @Override
   public String toString() {
      return super.toString() + "[model=" + model + "]";
   }
}
Code:
package my.tests.jpa.entities;
import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.PrimaryKeyJoinColumn;
@Entity
@DiscriminatorValue("PHONE")
@PrimaryKeyJoinColumn(name = "identifier")
public class Phone extends Device implements Serializable {
   private static final long serialVersionUID = 7154346535880588320L;
   @Basic
   private String bearer;
   public String getBearer() {
      return bearer;
   }
   public void setBearer(final String bearer) {
      this.bearer = bearer;
   }
   @Override
   public String toString() {
      return super.toString() + "[bearer=" + bearer + "]";
   }
}
Code:
package my.tests.jpa.entities;
import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.PrimaryKeyJoinColumn;
@Entity
@DiscriminatorValue("VEHICLE")
@PrimaryKeyJoinColumn(name = "identifier")
public class Vehicle extends Thing implements Serializable {
   private static final long serialVersionUID = 7046492255061930015L;
   @Basic
   private String number;
   public String getNumber() {
      return number;
   }
   public void setNumber(final String number) {
      this.number = number;
   }
   @Override
   public String toString() {
      return super.toString() + "[number=" + number + "]";
   }
}
and the DDL...
Code:
DROP INDEX IF EXISTS index_thing_owner CASCADE;
DROP INDEX IF EXISTS index_device_brand CASCADE;
DROP TABLE IF EXISTS person CASCADE;
DROP TABLE IF EXISTS thing CASCADE;
DROP TABLE IF EXISTS vehicle CASCADE;
DROP TABLE IF EXISTS device CASCADE;
DROP TABLE IF EXISTS phone CASCADE;
DROP TABLE IF EXISTS computer CASCADE;
DROP TABLE IF EXISTS brand CASCADE;
CREATE TABLE brand (
   code VARCHAR(16) PRIMARY KEY NOT NULL,
   name VARCHAR(64) NOT NULL
);
ALTER TABLE brand OWNER TO fifi;
CREATE TABLE person (
   identifier INTEGER PRIMARY KEY NOT NULL,
   name VARCHAR(64) NOT NULL
);
ALTER TABLE person OWNER TO fifi;
CREATE TABLE thing (
   identifier INTEGER PRIMARY KEY NOT NULL,
   description VARCHAR(128) NOT NULL,
   person_identifier INTEGER NOT NULL,
   kind_of_thing VARCHAR(16) NOT NULL,
   FOREIGN KEY (person_identifier) REFERENCES person (identifier)
);
ALTER TABLE thing OWNER TO fifi;
CREATE INDEX index_thing_owner ON thing (person_identifier);
CREATE TABLE vehicle (
   identifier INTEGER PRIMARY KEY NOT NULL,
   number VARCHAR(32) NOT NULL,
   FOREIGN KEY (identifier) REFERENCES thing (identifier)
);
ALTER TABLE vehicle OWNER TO fifi;
CREATE TABLE device (
   identifier INTEGER PRIMARY KEY NOT NULL,
   model VARCHAR(128) NOT NULL,
   brand_code VARCHAR(16) NOT NULL,
   FOREIGN KEY (identifier) REFERENCES thing (identifier),
   FOREIGN KEY (brand_code) REFERENCES brand (code)
);
ALTER TABLE device OWNER TO fifi;
CREATE INDEX index_device_brand ON device (brand_code);
CREATE TABLE phone (
   identifier INTEGER PRIMARY KEY NOT NULL,
   bearer VARCHAR(32) NOT NULL,
   FOREIGN KEY (identifier) REFERENCES device (identifier)
);
ALTER TABLE phone OWNER TO fifi;
CREATE TABLE computer (
   identifier INTEGER PRIMARY KEY NOT NULL,
   cpu VARCHAR(32) NOT NULL,
   FOREIGN KEY (identifier) REFERENCES device (identifier)
);
ALTER TABLE computer OWNER TO fifi;