-->
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: Likely bug on generated SQL on inheritance hierarchy
PostPosted: Thu Jun 04, 2015 3:04 am 
Newbie

Joined: Sat Feb 25, 2006 6:46 am
Posts: 9
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;


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.