首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Hibernate 5.4运行时字节码增强器enableLazyInitialization无法工作

Hibernate 5.4运行时字节码增强器enableLazyInitialization无法工作
EN

Stack Overflow用户
提问于 2021-03-17 20:58:39
回答 1查看 795关注 0票数 2

我以base教程项目(链接) >本机引导>注释示例为例。

Hibernate版本: 5.4.29

实体:

代码语言:javascript
复制
@Entity
public class Customer {
    
    @Id
    @GeneratedValue
    private Integer id;

    private String name;

    @Basic( fetch = FetchType.LAZY )
    private UUID accountsPayableXrefId;

    @Lob
    @Basic( fetch = FetchType.LAZY )
    @LazyGroup( "lobs" )
    private Blob image;

    // getters and setters

}

hibernate.cfg.xml中,我添加了以下行

代码语言:javascript
复制
<property name="hibernate.enhancer.enableLazyInitialization">true</property>

单元测试

代码语言:javascript
复制
public void testLazy() throws SerialException, SQLException {
    
    Session session = sessionFactory.openSession();
    session.beginTransaction();
    
    byte[] bytes = "A byte array".getBytes();
    Blob blob = new javax.sql.rowset.serial.SerialBlob(bytes);
    Customer customer = new Customer();
    customer.setName("John Doe");
    customer.setAccountsPayableXrefId(UUID.randomUUID());
    customer.setImage(blob);
    
    session.save( customer );
    
    Integer id = customer.getId();
    
    session.getTransaction().commit();
    session.close();

    session = sessionFactory.openSession();
    session.beginTransaction();
    
    Customer found = session.find(Customer.class, id);
    System.out.println("Customer: " + found.getAccountsPayableXrefId());
    System.out.println("Customer: " + found.getImage().length());

    session.getTransaction().commit();
    session.close();
}

我希望在实体提取字段中标记为lazy的字段甚至不会从DB中被选中,直到显式引用它们,但我在日志中看到:

代码语言:javascript
复制
Hibernate: select customer0_.id as id1_0_0_, customer0_.accountsPayableXrefId as accounts2_0_0_, customer0_.image as image3_0_0_, customer0_.name as name4_0_0_ from Customer customer0_ where customer0_.id=?

查询提供了相同的结果(懒惰= false)

代码语言:javascript
复制
List<Customer> result = session.createQuery( "from Customer" ).list();
for ( Customer c : result ) {
    System.out.println("Customer: " + c.getAccountsPayableXrefId());
    System.out.println("Customer: " + c.getImage().length());
}

在跟踪日志中有这样的行

代码语言:javascript
复制
[2021-03-17 20:44:10.349][][DBG][org.hibernate.cfg.Ejb3Column][main] Binding column: Ejb3Column{table=org.hibernate.mapping.Table(Customer), mappingColumn=accountsPayableXrefId, insertable=true, updatable=true, unique=false} 
[2021-03-17 20:44:10.349][][DBG][org.hibernate.cfg.annotations.PropertyBinder][main] MetadataSourceProcessor **property accountsPayableXrefId with lazy=true** 
...
[2021-03-17 20:44:10.351][][DBG][org.hibernate.cfg.annotations.PropertyBinder][main] MetadataSourceProcessor property image with lazy=true 
...
[2021-03-17 20:44:10.461][][DBG][org.hibernate.internal.SessionFactoryImpl][main] Instantiating session factory with properties: {... hibernate.enhancer.enableLazyInitialization=true} 
...
[... 20:44:11.382][][TRC][o.h.event.internal.DefaultLoadEventListener][main] Loading entity: [o.h.tutorial.annotations.Customer#1] 
[... 20:44:11.384][][TRC][o.h.persister.entity.AbstractEntityPersister][main] Fetching entity: [o.h.tutorial.annotations.Customer#1] 
[... 20:44:11.386][][DBG][o.h.SQL][main] select customer0_.id as id1_0_0_, customer0_.accountsPayableXrefId as accounts2_0_0_, customer0_.image as image3_0_0_, customer0_.name as name4_0_0_ from Customer customer0_ where customer0_.id=? 
[... 20:44:11.387][][TRC][o.h.type.descriptor.sql.BasicBinder][main] binding parameter [1] as [INTEGER] - [1] 
[... 20:44:11.457][][TRC][o.h.loader.plan.exec.process.internal.EntityReferenceInitializerImpl][main] hydrating entity state 
[... 20:44:11.459][][TRC][o.h.persister.entity.AbstractEntityPersister][main] Hydrating entity: [o.h.tutorial.annotations.Customer#1] 
[... 20:44:11.460][][TRC][o.h.type.descriptor.sql.BasicExtractor][main] extracted value ([accounts2_0_0_] : [BINARY]) - [a897b3c2-c19c-4f36-b0a1-17bca893f433] 
[... 20:44:11.464][][TRC][o.h.type.descriptor.sql.BasicExtractor][main] extracted value ([image3_0_0_] : [BLOB]) - [{blob}] 
[... 20:44:11.465][][TRC][o.h.type.descriptor.sql.BasicExtractor][main] extracted value ([name4_0_0_] : [VARCHAR]) - [John Doe] 
[... 20:44:11.466][][TRC][o.h.loader.plan.exec.process.internal.AbstractRowReader][main] Total objects hydrated: 1 
[... 20:44:11.467][][DBG][o.h.engine.internal.TwoPhaseLoad][main] Resolving attributes for [o.h.tutorial.annotations.Customer#1] 
[... 20:44:11.468][][DBG][o.h.engine.internal.TwoPhaseLoad][main] Processing attribute `accountsPayableXrefId` : value = a897b3c2-c19c-4f36-b0a1-17bca893f433 
[... 20:44:11.468][][DBG][o.h.engine.internal.TwoPhaseLoad][main] Attribute (`accountsPayableXrefId`)  - enhanced for lazy-loading? - false 
[... 20:44:11.468][][DBG][o.h.engine.internal.TwoPhaseLoad][main] Processing attribute `image` : value = blob0: X'412062797465206172726179' 
[... 20:44:11.468][][DBG][o.h.engine.internal.TwoPhaseLoad][main] Attribute (`image`)  - enhanced for lazy-loading? - false 
[... 20:44:11.468][][DBG][o.h.engine.internal.TwoPhaseLoad][main] Processing attribute `name` : value = John Doe 
[... 20:44:11.468][][DBG][o.h.engine.internal.TwoPhaseLoad][main] Attribute (`name`)  - enhanced for lazy-loading? - false 
[... 20:44:11.468][][DBG][o.h.engine.internal.TwoPhaseLoad][main] Done materializing entity [o.h.tutorial.annotations.Customer#1] 

所以看起来懒散加载对我的例子不起作用。我做错什么了?

EN

回答 1

Stack Overflow用户

发布于 2021-06-08 17:05:03

尝试使用“域模型的构建时增强”而不是运行时。设置更简单,效率更高,因为在编译过程中更改了实体的字节码:

代码语言:javascript
复制
<build>
  <plugins>
    [...]
    <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>
          </configuration>
          <goals>
            <goal>enhance</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
    [...]
  </plugins>
</build>

之后,在实体类中,您可以使用@Basic( fetch = FetchType.LAZY )注释来加载延迟列:

代码语言:javascript
复制
@Entity
public class Customer {
    
    @Id
    @GeneratedValue
    private Integer id;

    private String name;

    @Basic( fetch = FetchType.LAZY )
    private UUID accountsPayableXrefId;

    @Basic( fetch = FetchType.LAZY )
    private Blob image;

    // getters and setters
}

若要验证,请将SQL添加到application.yaml文件中:

代码语言:javascript
复制
spring:
  jpa:
    properties:
      hibernate.show_sql: true
      hibernate.format_sql: true
logging:
  level:
    org.hibernate.type.descriptor.sql.BasicBinder: TRACE

并使用maven构建应用程序,因为如果尝试从IntelliJ或Eclipse中运行该插件,则不会调用该插件:

代码语言:javascript
复制
./mvnw clean spring-boot:run
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66681126

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档