mapping Hibernate query results to custom class?

前端 未结 8 747
时光说笑
时光说笑 2020-12-01 11:02

Following up on a question I posted yesterday: How to populate POJO class from custom Hibernate query?

Can someone show me an example of how to code the following SQ

8条回答
  •  盖世英雄少女心
    2020-12-01 11:27

    Writing (exist this type of Challenges working with hibernate)

    1. Custom Queries
    2. Custom Queries with Optional Parameters
    3. Mapping Hibernate Custom query results to Custom class.

    I am not saying about custom EntityRepository interface which extends JpaRepository on SpringBoot which you can write custom Query with @Query -> here you can't write query with optional params e.g. if param is null don't append it in query string. And you can use Criteria api of hibernate but it not recommended in their documentation because of performance issue...

    But exist simple and error prone and performance good way...

    Write your own QueryService class which are methods will get string(answer for first and second problem) sql and will map result to Custom class (third problem) with it's any association @OneToMany, @ManyToOne ....

    @Service
    @Transactional
    public class HibernateQueryService {
    
        private final Logger log = LoggerFactory.getLogger(HibernateQueryService.class);
        private JpaContext jpaContext;
    
        public HibernateQueryService(JpaContext jpaContext) {
            this.jpaContext = jpaContext;
        }
    
        public List executeJPANativeQuery(String sql, Class entity){
            log.debug("JPANativeQuery executing: "+sql);
            EntityManager entityManager = jpaContext.getEntityManagerByManagedType(Article.class);
            return entityManager.createNativeQuery(sql, entity).getResultList();
        }
    
    /**
     * as annotation @Query -> we can construct here hibernate dialect 
     * supported query and fetch any type of data
     * with any association @OneToMany and @ManyToOne.....
     */
        public List executeHibernateQuery(String sql, Class entity){
            log.debug("HibernateNativeQuery executing: "+sql);
            Session session = jpaContext.getEntityManagerByManagedType(Article.class).unwrap(Session.class);
            return session.createQuery(sql, entity).getResultList();
        }
    
    public  List executeGenericHibernateQuery(String sql, Class entity){
        log.debug("HibernateNativeQuery executing: "+sql);
        Session session = jpaContext.getEntityManagerByManagedType(Article.class).unwrap(Session.class);
        return session.createQuery(sql, entity).getResultList();
    }
    
    
    }
    

    Use case - you can write any type condition about query params

     @Transactional(readOnly = true)
        public List findWithHibernateWay(SearchFiltersVM filter){
    
            Long[] stores = filter.getStores();
            Long[] categories = filter.getCategories();
            Long[] brands = filter.getBrands();
            Long[] articles = filter.getArticles();
            Long[] colors = filter.getColors();
    
            String query = "select article from Article article " +
                "left join fetch article.attributeOptions " +
                "left join fetch article.brand " +
                "left join fetch article.stocks stock " +
                "left join fetch stock.color " +
                "left join fetch stock.images ";
    
    boolean isFirst = true;
    
            if(!isArrayEmptyOrNull(stores)){
                query += isFirst ? "where " : "and ";
                query += "stock.store.id in ("+ Arrays.stream(stores).map(store -> store.toString()).collect(Collectors.joining(", "))+") ";
                isFirst = false;
            }
    
            if(!isArrayEmptyOrNull(brands)){
                query += isFirst ? "where " : "and ";
                query += "article.brand.id in ("+ Arrays.stream(brands).map(store -> store.toString()).collect(Collectors.joining(", "))+") ";
                isFirst = false;
            }
    
            if(!isArrayEmptyOrNull(articles)){
                query += isFirst ? "where " : "and ";
                query += "article.id in ("+ Arrays.stream(articles).map(store -> store.toString()).collect(Collectors.joining(", "))+") ";
                isFirst = false;
            }
    
            if(!isArrayEmptyOrNull(colors)){
                query += isFirst ? "where " : "and ";
                query += "stock.color.id in ("+ Arrays.stream(colors).map(store -> store.toString()).collect(Collectors.joining(", "))+") ";
            }
    
            List
    articles = hibernateQueryService.executeHibernateQuery(query, Article.class); /** * MapStruct [http://mapstruct.org/][1] */ return articles.stream().map(articleMapper::toDto).collect(Collectors.toList()); }

提交回复
热议问题