简体   繁体   中英

Hibernate @LazyToOne(LazyToOneOption.NO_PROXY) @OneToOne(fetch = FetchType.LAZY) always fetched eagerly

My goal is to enable lazy loading for a bidirectional ono-to-one association on the parent-side of the association. Consider the following two entities:

Parent Vendor.java :

@Entity
@Audited
@NoArgsConstructor
@Getter
public class Vendor extends User {

    @JoinColumn(nullable = false, unique = true, updatable = false)
    @LazyToOne(LazyToOneOption.NO_PROXY)
    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "vendor", optional = false, orphanRemoval = true)
    private Operator operator;

}

Child Operator.java :

@Entity
@Audited
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Getter
public class Operator {

    @Id
    private Long id;

    @JoinColumn(name = "id")
    @MapsId
    @OneToOne(fetch = FetchType.LAZY, optional = false)
    private Vendor vendor;

}

Note: I omitted other fields, constructors and equals/hashCode functions for brevity.

As mentioned before, my goal is to load the vendor's operator lazyly. Therefore following the Hibernate user guide and Vlad Mihalcea's tutorial on how to enable bytecode enhancement in Hibernate , I annotated the parent-side association with @LazyToOne(LazyToOneOption.NO_PROXY) in addtion to the @OneToOne with fetch = FetchType.LAZY . After adding the following plugin to my pom.xml , the operator is still loaded eagerly upon fetching the vendor.

Plugin configuration:

      <plugin>
        <groupId>org.hibernate.orm.tooling</groupId>
        <artifactId>hibernate-enhance-maven-plugin</artifactId>
        <version>${hibernate.version}</version>
        <executions>
          <execution>
            <configuration>
              <failOnError>true</failOnError>
              <enableLazyInitialization>true</enableLazyInitialization>
              <enableDirtyTracking>true</enableDirtyTracking>
              <enableAssociationManagement>true</enableAssociationManagement>
            </configuration>
            <goals>
              <goal>enhance</goal>
            </goals>
          </execution>
        </executions>
      </plugin>

When I fetch a vendor, the following SQL is generated:

2019-10-18 13:43:16.138  INFO 12212 --- [           main] n.t.d.l.l.SLF4JQueryLoggingListener      : 
Name:dataSource, Connection:8, Time:2, Success:True
Type:Prepared, Batch:False, QuerySize:1, BatchSize:0
Query:["select vendor0_.id as id1_39_0_, vendor0_1_.created_at as created_2_39_0_, vendor0_1_.version as version3_39_0_, vendor0_1_.account_non_locked as account_4_39_0_, vendor0_1_.email as email5_39_0_, vendor0_1_.email_verified as email_ve6_39_0_, vendor0_1_.enabled as enabled7_39_0_, vendor0_1_.last_password_reset_date as last_pas8_39_0_, vendor0_1_.password as password9_39_0_, vendor0_.address_district as address_1_43_0_, vendor0_.address_latitude as address_2_43_0_, vendor0_.address_longitude as address_3_43_0_, vendor0_.address_city as address_4_43_0_, vendor0_.address_country_code as address_5_43_0_, vendor0_.address_street as address_6_43_0_, vendor0_.address_street_no as address_7_43_0_, vendor0_.address_zip_code as address_8_43_0_, vendor0_.contact_details_email as contact_9_43_0_, vendor0_.contact_details_phone as contact10_43_0_, vendor0_.customer_no_customer_no as custome17_43_0_, vendor0_.description as descrip11_43_0_, vendor0_.hidden as hidden12_43_0_, vendor0_.name as name13_43_0_, vendor0_.slug as slug14_43_0_, vendor0_.verified as verifie15_43_0_ from vendor vendor0_ inner join users vendor0_1_ on vendor0_.id=vendor0_1_.id where vendor0_.id=?"]
Params:[(4)]

2019-10-18 13:43:16.141  INFO 12212 --- [           main] n.t.d.l.l.SLF4JQueryLoggingListener      : 
Name:dataSource, Connection:8, Time:1, Success:True
Type:Prepared, Batch:False, QuerySize:1, BatchSize:0
Query:["select operator0_.id as id1_17_0_, operator0_.address_city as address_2_17_0_, operator0_.address_country_code as address_3_17_0_, operator0_.address_street as address_4_17_0_, operator0_.address_street_no as address_5_17_0_, operator0_.address_zip_code as address_6_17_0_, operator0_.bank_account_bic as bank_acc7_17_0_, operator0_.bank_account_iban as bank_acc8_17_0_, operator0_.bank_account_owner as bank_acc9_17_0_, operator0_.company as company10_17_0_, operator0_.contact_details_email as contact11_17_0_, operator0_.contact_details_phone as contact12_17_0_, operator0_.contact_person_first_name as contact13_17_0_, operator0_.contact_person_gender as contact14_17_0_, operator0_.contact_person_last_name as contact15_17_0_, operator0_.tax_id as tax_id16_17_0_, operator0_.vat_id as vat_id17_17_0_ from operator operator0_ where operator0_.id=?"]
Params:[(4)]

When I comment out the operator field in Vendor.java , only the first statement is generated. I also tried setting the spring.jpa.properties.hibernate.ejb.use_class_enhancer property as suggested in this answer , but it didn't change the generated SQL. My apprehension is that this issue might be related to the mapping with @MapsId in Operator.java as this is not used in the Hibernate example .

Version of used frameworks:
Spring Boot 2.1.9.RELEASE
Hibernate 5.3.12.Final

My mistake was to place the hibernate-enhance-maven-plugin to early in the plugin list of the <build> part in the pom.xml , namely before the maven-compiler-plugin . After placing it at the end of the <plugins> list, it worked as expected.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM