Hibernate is making extra SQL statement with @ManyToOne and @Lazy fetching object

我的未来我决定 提交于 2020-01-25 07:58:43

问题


I would like someone to explain me why Hibernate is making one extra SQL statement in my straight forward case. Basically i have this object:

@Entity
class ConfigurationTechLog (
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        val id: Long?,

        val configurationId: Long,

        val type: String,

        val value: String?
) {
        @JsonIgnore
        @ManyToOne(fetch = FetchType.LAZY)
        @JoinColumn(name = "configurationId", insertable = false, updatable = false)
        val configuration: Configuration? = null
}

So as you can see, nothing special there. And when i execute this query :

@Query(value = "SELECT c FROM ConfigurationTechLog c where c.id = 10")
fun findById10() : Set<ConfigurationTechLog>

In my console i see this:

Hibernate: 
    /* SELECT
        c 
    FROM
        ConfigurationTechLog c 
    where
        c.id = 10 */ select
            configurat0_.id as id1_2_,
            configurat0_.configuration_id as configur2_2_,
            configurat0_.type as type3_2_,
            configurat0_.value as value4_2_ 
        from
            configuration_tech_log configurat0_ 
        where
            configurat0_.id=10
Hibernate: 
    select
        configurat0_.id as id1_0_0_,
        configurat0_.branch_code as branch_c2_0_0_,
        configurat0_.country as country3_0_0_,
        configurat0_.merchant_name as merchant4_0_0_,
        configurat0_.merchant_number as merchant5_0_0_,
        configurat0_.org as org6_0_0_,
        configurat0_.outlet_id as outlet_i7_0_0_,
        configurat0_.platform_merchant_account_name as platform8_0_0_,
        configurat0_.store_type as store_ty9_0_0_,
        configurat0_.terminal_count as termina10_0_0_ 
    from
        configuration configurat0_ 
    where
        configurat0_.id=?

Can someone please explain me, what is happening here ? From where this second query is coming from ?


回答1:


I assume you are using Kotlin data class. The kotlin data class would generate toString, hashCode and equals methods utilizing all the member fields. So if you are using the returned values in your code in a way that results in calling of any of these method may cause this issue.

BTW, using Kotlin data claases is against the basic requirements for JPA Entity as data classes are final classes having final members.




回答2:


Try below query, it seems you ran into N+1 problem for ManyToOne when using Query,

@Query(value = "SELECT c FROM ConfigurationTechLog c join fetch c.configuration config where c.id = 10")
fun findById10() : Set<ConfigurationTechLog>

It should get all the data in a single SQL query using join.




回答3:


In order to make an association lazy, Hibernate has to create a proxy instance instead of using the real object, i.e. it needs to create an instance of dynamically generated subclass of the association class.

Since in Kotlin all classes are final by default, Hibernate cannot subclass it so it has to create the real object and initialize the association right away. In order to verify this, try declaring the Configuration class as open.

To solve this without the need to explicitly declare all entities open, it is easier to do it via the kotlin-allopen compiler plugin.



来源:https://stackoverflow.com/questions/59849508/hibernate-is-making-extra-sql-statement-with-manytoone-and-lazy-fetching-objec

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!