0

I have a database structure that is unfortunately out of my control. I am trying to write a jpql query to query on a list of values that is using a parent entity but it is not returning any values.

Classes

This class is probably the root of the problem it has a collection of TagUsage that all the children should have as a collection, but the database is creating a separate join table for all inherited types. Is this happening because of TABLE_PER_CLASS?

@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Organization extends DomainEntity implements Serializable {

    @ManyToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST})
    private List<TagUsage> tagUsages = new ArrayList<TagUsage>();

    public Organization() {
    }
    ...


@Entity
@Table(name = "tag_usage", indexes = {
    @Index(columnList = "id"),
    @Index(columnList = "name")
})
public class TagUsage extends DomainEntity implements Serializable {


    @ManyToOne(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
    @JoinColumn(name = "tagbag_id", referencedColumnName = "id")
    private TagBag tagBag;

    @ManyToMany(mappedBy = "tagUsages")
    private List<Organization> organizations;
...

I am trying to run the named query "TagBag.findWithOrganizations" but when I do this doesn't return me any results.

@Entity
@Table(name = "tag_bag", indexes = {
    @Index(columnList = "id")})
@NamedQueries({
    @NamedQuery(name = "TagBag.findWithOrganizations", query = "SELECT t from TagBag t LEFT JOIN FETCH t.tagUsages u LEFT JOIN FETCH u.organizations o where t.id = :id")})
public class TagBag extends DomainEntity implements Serializable {

@OneToMany(targetEntity = TagUsage.class, mappedBy = "tagBag", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<TagUsage> tagUsages;

There are multiple classes that extend the Organization class. I am trying to figure out if I can even write a query to fetch all inherited types of Organization TagBag.findWithOrganizations.

BTW my issue comes down to this, when the query tries to fetch the Organizations from the TagUsage class it is querying the organization_tag_usage join table and not descending down to all the inherited types to query their own *_tag_usage table.

Also it we are using eclipselink if that makes any difference.

Update

I have diagnosed the issue but am unsure why it is happening. Looking at the sql output I see that when I try to fetch the organizations that are attached to each one of the tag usages it is using the wrong join table for the query.

Here is one sample that occurrs for each of the inheriting objects of Organization. In this case there is a class called OrgSystem which inherits from the Organizaiton class. The database has a join table for tag usages created for all the inheriting tables of Organization along with a join table for the Organization class itself. Whenever a TagUsage is added to a class that inherits from Organization the relationship is represented in that classes join table. For example in this case the OrgSystem has a table called orgsystem_tag_usages. But when jpa (eclipselink) tries to fetch the relationships it is always joining using the organization_tag_usages table.

SELECT t1.id, t1.DESCRIPTION, t1.NAME, t1.VID FROM ORGANIZATION_tag_usage t0, ORGSYSTEM t1 WHERE ((t0.tagUsages_id = ?) AND (t1.id = t0.organizations_id))
    bind => [38]

Postgres output for the list of organization tables.

\dt
| public   | organization             | table  |  |
| public   | organization_tag_usage   | table  |  |
| public   | orgcustomer              | table  |  |
| public   | orgcustomer_tag_usage    | table  |  |
| public   | orgdevice                | table  |  |
| public   | orgdevice_tag_usage      | table  |  |
| public   | orgmasteragent           | table  |  |
| public   | orgmasteragent_tag_usage | table  |  |
| public   | orgsite                  | table  |  |
| public   | orgsite_tag_usage        | table  |  |
| public   | orgsystem                | table  |  |
| public   | orgsystem_tag_usage      | table  |  |

As you can see here the organization_tag_usage is completely empty but the actual join table that the query should be using is orgsystem_tag_usage.

select * from organization_tag_usage;
SELECT 0
select * from orgsystem_tag_usage
+----------------+----------------+
|   orgsystem_id |   tagusages_id |
|----------------+----------------|
|              1 |             10 |
|              1 |             16 |
|              1 |             17 |
|              1 |             18 |
|              3 |             19 |
|              3 |             20 |
|              2 |             23 |
|              1 |             25 |
|              1 |             26 |
|              1 |             27 |
|              2 |             30 |
|              1 |             38 |
|              1 |             39 |
|              1 |             52 |
|              3 |             53 |
|              3 |             54 |
+----------------+----------------+
SELECT 16

Is this a bug in eclipselink?

Chris Hinshaw
  • 6,967
  • 2
  • 39
  • 65
  • 1
    I'm surprised you don't get an exception as JPA does not allow aliasing join fetches: http://stackoverflow.com/questions/8195252/jpa-fetch-join-query (just checked, support was added in EL 2.4). Can you show the SQL that is generated? – Chris Jan 16 '15 at 14:41
  • Thanks Chris for the response, yes I do get an error in the ide. But eclipselink supports this natively. I have also tried doing this without the join fetches and the problem persists. I have diagnosed the problem using the sql and will update the question in just a second – Chris Hinshaw Jan 16 '15 at 15:31
  • 1
    It should use the organization_tag_usages table, as that is what you have told the u.organizations mapping to use. The organizations mapping specifies that it is mapped by the Organization.tagUsages mapping, which is using the JPA default 'organization_tag_usages' table. – Chris Jan 16 '15 at 21:43
  • But it is creating the *_tag_usages table for all the child objects also. When an organization is saved with a reference to the TagUsage it is added to the descendents join table. So for instance if a tag usage is added to an OrgSystem which inherits from Organization it is actually adding the reference in the orgsystem_tag_usage table and not in the organization_tag_usage. I also converted the Organization table to be abstract and the database recreated the organization and organization_tag_usage tables after I deleted them and restarted. This seems odd. It is an @Entity but it is abstract. – Chris Hinshaw Jan 16 '15 at 22:32
  • One more quick question that leads me to believe why it is creating multiple join tables for all the child entities. Is it normal to create a sequence to generate ids for each and every table. This would make sense why it thinks it needs to create child join tables because it wouldn't be able to put the unique id in the organization_tag_usages. If the table had a single sequence for generating ids then it could use the organization_tag_usage knowing that every inherited object from organization would have a unique id. I didn't create this database structure so I don't know the thought process. – Chris Hinshaw Jan 16 '15 at 22:35

0 Answers0