Home > Blockchain >  Hibernate generates different queries for same code
Hibernate generates different queries for same code

Time:10-19

We just fixed a behaviour in Hibernate where, on the local machine, it generated a different query than on the Staging server. Can anyone of you explain to me, why

@NotNull
@OneToOne(fetch = FetchType.EAGER)
@Type(type = "user_account")
open var user: T

gets translated locally to

from
user_password abstractpa0_
left outer join user_account basicaccou1_ on abstractpa0_.user_id=basicaccou1_.id

and on the server, running dockerized on Kubernetes, it gets translated into

from user_password abstractpa0_
left outer join d21_user_account useraccoun1_ on abstractpa0_.user_id = useraccoun1_.id
left outer join user_account useraccoun1_1_ on useraccoun1_.id = useraccoun1_1_.id

We use a single table inheritance strategy. The base class is the AbstractPasswordEntity

@Entity(name = "user_password")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "user_type")
abstract class AbstractPasswordEntity<T : BasicAccountEntity>(

    ...

    @NotNull
    @OneToOne(fetch = FetchType.EAGER)
    @Type(type = "user_account")
    open var user: T

) : BaseEntity()

which gets implemented by Customer

@Entity(name = "CustomerPassword")
@DiscriminatorValue("CustomerPasswordEntity")
class CustomerPasswordEntity(

    id: Long? = null,
    passwordHash: String,
    user: CustomerAccountEntity

) : AbstractPasswordEntity<CustomerAccountEntity>(..., user)

and Staff classes.

@Entity(name = "StaffPassword")
@DiscriminatorValue("StaffPasswordEntity")
class StaffPasswordEntity(

    id: Long? = null,
    passwordHash: String,
    user: StaffAccountEntity

) : AbstractPasswordEntity<StaffAccountEntity>(..., user)

We could fix the behaviour after a day of bug fixing and a lot of WTF by changing the relationship annotation in AbstractPasswordEntity to

@Entity(name = "user_password")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "user_type")
abstract class AbstractPasswordEntity<T : BasicAccountEntity>(

    ...

    @NotNull
    @OneToOne(fetch = FetchType.EAGER, targetEntity = BasicAccountEntity::class)
    open var user: T

) : BaseEntity()

This now compiles and executes on all environments the same way. The only thing I don't have is an understanding of what did just happen and why.

Funfact: The jars from staging and locally, compared with pkgdiff and md5deep, showed exactly the same result - except for the GitLab properties.

CodePudding user response:

As this topic could not draw any replies, here's our best guess:

It's an issue with generics. They get deleted on runtime and we run into a sorting issue. Locally it runs because, by accident, the order of the classes within hibernate leads to the expected result. On staging, the order gets mixed up, hibernate uses the first fitting class for the generic which then leads to a different query being executed. So explicitly specifying the parent BasicAccountEntity as entry point did resolve it issue.

As I said, best guess.

  • Related