Hibernate 5->6: Generating extra columns in select on joined tables inheritance strategy

Hibernate 6 is selecting extra columns on a joined table strategy when specifying the parent class in the query. When there is a large hierarchy, it causes an error when it exceeds 1664 columns (Postgres). Is there any configuration change to make it to avoid selecting all these unnecessary columns?

This also makes eager loading not work in the parent class with a large hierarchy.

In this example with A being the parent, and B, C, D are joined tables.
Getting one of the subclasses D, but passing in the superclass:

Example query:
session.get(A.class, id);

Generated SQL:
hibernate 6.1.7:
select a1_0.ID,a1_0.DISCRIMINATOR,a1_0.FIELDA,a1_0.PARENTID,a1_1.FIELDB,a1_2.FIELDC,a1_3.FIELDD from A a1_0 left join B a1_1 on a1_0.ID=a1_1.ID left join C a1_2 on a1_0.ID=a1_2.ID left join D a1_3 on a1_0.ID=a1_3.ID where a1_0.ID=?
hibernate 5.5.3:
select a0_.ID as id1_0_0_, a0_.FIELDA as fielda3_0_0_, a0_.PARENTID as parentid4_0_0_, a0_.DISCRIMINATOR as discrimi2_0_0_ from A a0_ where a0_.ID=?
select a_3_.FIELDD as fieldd2_24_ from D a_3_ where a_3_.ID=?

This example hierarchy is mixed with a discriminator using XML, but the same behavior was seen with a pure joined table strategy as well.

XML Files:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="test">
	<class name="A" table="A" dynamic-insert="true" dynamic-update="true" select-before-update="true" discriminator-value="A">
	<cache usage="read-write"/>
	<id name="id" column="ID">
		<generator class="increment"/>
	</id>
	<discriminator column="DISCRIMINATOR" type="string" length="30"/>
	<property name="fielda" type="string" column="FIELDA" length="100" />
        <many-to-one name="parentId" column="PARENTID" class="A" lazy="false"/>
</class>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<subclass name="test.B" extends="test.A" dynamic-insert="true" dynamic-update="true" select-before-update="true" discriminator-value="B">
    <join table="B" fetch="select">
    <key on-delete="cascade">
        <column name="ID"/>
    </key>
    <property name="fieldb" type="string" column="FIELDB" length="100"/>
    </join>
</subclass>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<subclass name="test.C" extends="test.A" dynamic-insert="true" dynamic-update="true" select-before-update="true" discriminator-value="C">
    <join table="C" fetch="select">
    <key on-delete="cascade">
        <column name="ID"/>
    </key>
    <property name="fieldc" type="string" column="FIELDC" length="100"/>
    </join>
</subclass>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<subclass name="test.D" extends="test.A" dynamic-insert="true" dynamic-update="true" select-before-update="true" discriminator-value="D">
    <join table="D" fetch="select">
    <key on-delete="cascade">
        <column name="ID"/>
    </key>
    <property name="fieldd" type="string" column="FIELDD" length="100"/>
    </join>
</subclass>
</hibernate-mapping>

JAVA Classes:

package test;
public class A {
    private String fielda;
    private Long id;
    private A parentId;
...
}
package test;
public class B extends A {
    private String fieldb;
...
}
package test;
public class C extends A {
    private String fieldc;
...
}
package test;
public class D extends A {
    private String fieldd;
...
}

If you want to implement fetching of an entity with 2 queries, you’ll have to implement that yourself. You can use something like this:

Class<? extends A> resultType = session.createQuery("select type(a) from A a where a.id = :param", Class.class).setParameter("id", id).getSingleResult();
A result = session.find(resultType, id);

Thanks, but is there any way to accomplish this in the eager loading of the many-to-one relationship?

Not that I am aware of. Maybe ask this question on our chat platform Zulip and see what others think about this. I don’t think that it is a bug to emit the joins, but maybe others do.

Hi,

I am facing a similar issue while upgrading from Hibernate 5 to Hibernate 6. Our data model also uses inheritance ( InheritanceType .JOINED). The same model works fins with MySql. Only SQL Server is giving us this exception. Is there something that can be done about this? We also use a mix for EAGER and LAZY loading.

Thanks in advance.

Please create a new topic and share more details about your problem.