4

I am doing a migration to Spring Boot 3 from version 2.1 and I made an upgrade to Hibernate:6.1.7.Final.

After doing so I encountered what it seems like an incompatibility with the olders versions of Hibernate and the new ones.

I have a 4 classes definitions as follows:

@Table(name = "a")
@DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.STRING)
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class AClass {

    public abstract String getAttribute();

    public abstract void setAttribute(String attribute);

}

@Entity
@Table(name = "b")
@DiscriminatorValue("B")
@DiscriminatorOptions(force = true)
public class BClass extends AClass {

    @Column(name ="attribute")
    private String attribute;

    //other attributes ...

    public String getAttribute(){
        return this.attribute;
    }

    public void setAttribute(String attribute){
        this.attribute = attribute;
    }
}

@Entity
@Table(name = "c")
@DiscriminatorValue("C")
@DiscriminatorOptions(force = true)
public class CClass extends AClass {
     @Column(name = "attribute")
     private String attribute;

    //other attributes ...

    @Override
    public String getAttribute(){
        return this.attribute;
    }

    @Override
    public void setAttribute(String attribute){
        this.attribute = attribute;
    }
}

@Entity
@Table(name = "d")
@DiscriminatorValue("D")
@DiscriminatorOptions(force = true)
public class DClass extends AClass {
     @Column(name = "attributeA")
     private String attributeA; //the attribute changes name in this class

    //other attributes ...

    @Override
    public String getAttribute(){
        return this.attributeA;
    }

    @Override
    public void setAttribute(String attribute){
        this.attributeA = attribute;
    }
}

Finally the error appears when I tried to call the following method findByAttribute:

@Repository
public interface ARepository<T extends AClass> extends JpaRepository<T, Long>, JpaSpecificationExecutor<T> {

    @Query("SELECT a " +
            "FROM AClass a " +
            "WHERE a.attribute=:attribute"
    )
    T findByAttribute(@Param("attribute") String attribute);
   ....
}

@Service
public class AClassService {
     @Autowired
     private ARepository<A> aRepository;

     AClass findByAttribute(String attribute){
        return aRepository.findByAttribute(attribute)
     }
}

The exception:

org.springframework.dao.InvalidDataAccessApiUsageException:
org.hibernate.query.SemanticException: 
Could not resolve attribute 'attribute' of 'AClass' 
due to the attribute being declared in
multiple sub types: ['BClass', 'CClass'] at
org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccesExceptionIfPossible(EntityManagerFactoryUtils.java:371)

I think I understand the problem. Hibernate cannot determine where is each class attribute located. The simpler solution could be add the attribute column in the AClass instead of implementing it on each subclass. However the DClass changes the attributes name and the column is not longer the same. That prevents me from doing this change. I also don't understand why it worked before and now it does not work anymore?

Thanks !

2
  • DClass only changes the column, why would the field name need to change? You can declare them all in AClass and for DClass use the @AttributeOverride to change the column mapping for the attribute field.
    – M. Deinum
    Commented May 17, 2023 at 13:22
  • I tried to do that but : Using @AttributeOverride or @AttributeOverrides in conjunction with entity inheritance is not supported: DClass. The overriding definitions are ignored. Commented May 19, 2023 at 8:53

0