简体   繁体   中英

Hibernate initialize lazy field with projection

I have two entites A, B, C with the following mappings.

@Enttiy
class A {
   @OneToMany
   private List<B> Bs;
}

@Entity
class B {
   @OneToMany
   private List<C> Cs;
}

@Entity
class C {
   private Double x1;
   private Double y1;
   private Double z1;

   private Double x2;
   private Double y2;
   private Double z2;
   
   //...
}

The class C is a table mapped from a CSV and therefore has many columns.

In my code I need to use aRespository.findAll(spec) and iterate over all Bs and all its Cs. The user can select a subset of C's colums (lets say [x1, x2, z2] ). So the sql select from table would be simplified to just select x2, x2, z2 form C .

Is writing a custom query with using a ResultTransformer the best option? or is there a simpler alternative. Since the query is written for .netity A, but modified only entity C. I would also like to preserve the lazy loading if possible.

Thank you.

IMO you should use a DTO approach for this. Lazy loading for basic attributes needs additional setup and is not really worth it. It's much better to tell the database as much as possible about what data you want.

I think this is a perfect use case forBlaze-Persistence Entity Views .

I created the library to allow easy mapping between JPA models and custom interface or abstract class defined models, something like Spring Data Projections on steroids. The idea is that you define your target structure(domain model) the way you like and map attributes(getters) via JPQL expressions to the entity model.

A DTO model for your use case could look like the following with Blaze-Persistence Entity-Views:

@EntityView(A.class)
public interface ADto {
    @IdMapping
    Long getId();
    Set<BDto> getBs();

    @EntityView(B.class)
    interface BDto {
        @IdMapping
        Long getId();
        Set<CDto> getCs();
    }

    @EntityView(C.class)
    interface CDto {
        @IdMapping
        Long getId();
        Double getX1();
        Double getX2();
        Double getZ2();
    }
}

Querying is a matter of applying the entity view to a query, the simplest being just a query by id.

ADto a = entityViewManager.find(entityManager, ADto.class, id);

The Spring Data integration allows you to use it almost like Spring Data Projections: https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features

Page<ADto> findAll(Pageable pageable);

The best part is, it will only fetch the state that is actually necessary!

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