Spring Jpa规范和Eager loading

时间:2015-12-09 11:38:03

标签: spring jpa spring-boot spring-data-jpa

如何通过Jpa Specification

获取包含其类别的tiket列表

示例模型:

@Entity
@Table(name = "tickets")
public class Ticket {

@Id
private Integer id;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "category_id")
private Category 
}

服务方式:

public Page<Ticket> findAll(Pageable pageable) {
        return ticketRepository.findAll((root, query, cb) -> {
            root.join("category");
            return query.getRestriction();
        }, pageable);
}

3 个答案:

答案 0 :(得分:1)

我能够通过使用fetch而不是join来急切加载集合。

public Page<Ticket> findAll(Pageable pageable) {
    return ticketRepository.findAll((root, query, cb) -> {
        root.fetch("category");
        return query.getRestriction();
    }, pageable);
}

fetch方法将使用默认的连接类型(内部)。如果要加载没有类别的票证,则必须将JoinType.LEFT作为第二个参数传递。

答案 1 :(得分:0)

要加载Lazy关系,您有一些方法。一些主要使用的是:

计算要加载的列表

那是什么?所以,你需要用关系“做点什么”,所以它可以被加载。所以你可以打电话给

List<Tiket> tickets = ticketRepository.findAll();
for(Ticket t : tickets){
   t.category.name;
}

这样,您强制JPA查询类别。可是等等!问题是你会有很多额外的查询(在大的情况下,可能是性能问题)。所以,大多数时候最好的解决方案是另一个。

自定义JPA查询

您应该进入存储库界面并创建一个带有@Query注释的新方法来获取关系。类似的东西:

SELECT t FROM Ticket t JOIN FETCH t.category

答案 2 :(得分:0)

正如他们所说的那样,stackoverflow给出了stackoverflow来解决问题。 很久以前我就把这个课程从这个课堂上拿走了,随便回收它......

import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;

import org.apache.commons.beanutils.PropertyUtils;
import org.hibernate.Hibernate;

public class BeanLoader {
    /**
     * StackOverflow safe, if called before json creation, cyclic object must be avoided
     */
    public static void eagerize(Object obj)  {
        if(!Hibernate.isInitialized(obj))
            Hibernate.initialize(obj);
        PropertyDescriptor[] properties = PropertyUtils.getPropertyDescriptors(obj);
        for (PropertyDescriptor propertyDescriptor : properties) {
            Object origProp = null;
            try {
                origProp = PropertyUtils.getProperty(obj, propertyDescriptor.getName());
            } catch (IllegalAccessException e) {
                // Handled, but hopefully dead code  
                origProp=null;
            } catch (InvocationTargetException e) {
                // Single catch for obsolete java developers!
                origProp=null;
            } catch (NoSuchMethodException e) {
                // Single catch for obsolete java developers!
                origProp=null;
            }
            if (origProp != null 
                    && origProp.getClass().getPackage().toString().contains("domain")) {
                eagerize(origProp, new ArrayList<String>());
            }
            if (origProp instanceof Collection) {               
                for (Object item : (Collection) origProp) {
                    if (item.getClass().getPackage().toString().contains("domain")){
                        eagerize(item, new ArrayList<String>());
                    }
                }
            }
        }
    }

    /**
     * StackOverflows if passed a bean containing cyclic fields. Call only if sure that this won't happen!
     */
    public static void eagerizeUnsafe(Object obj)  {
        if(!Hibernate.isInitialized(obj))
            Hibernate.initialize(obj);
        PropertyDescriptor[] properties = PropertyUtils.getPropertyDescriptors(obj);
        for (PropertyDescriptor propertyDescriptor : properties) {
            Object origProp = null;
            try {
                origProp = PropertyUtils.getProperty(obj, propertyDescriptor.getName());
            } catch (IllegalAccessException e) {
                // Handled, but hopefully dead code  
                origProp=null;
            } catch (InvocationTargetException e) {
                // Single catch for obsolete java developers!
                origProp=null;
            } catch (NoSuchMethodException e) {
                // Single catch for obsolete java developers!
                origProp=null;
            }
            if (origProp != null 
                    && origProp.getClass().getPackage().toString().contains("domain")) {
                eagerize(origProp);
            }
            if (origProp instanceof Collection) {               
                for (Object item : (Collection) origProp) {
                    if (item.getClass().getPackage().toString().contains("domain")){
                        eagerize(item);
                    }
                }
            }
        }
    }

    private static void eagerize(Object obj, ArrayList<String> visitedBeans)  {
        if (!visitedBeans.contains(obj.getClass().getName())){
            visitedBeans.add(obj.getClass().getName());
        } else {
            return;
        }
        if(!Hibernate.isInitialized(obj))
            Hibernate.initialize(obj);
        PropertyDescriptor[] properties = PropertyUtils.getPropertyDescriptors(obj);
        for (PropertyDescriptor propertyDescriptor : properties) {
            Object origProp = null;
            try {
                origProp = PropertyUtils.getProperty(obj, propertyDescriptor.getName());
            } catch (IllegalAccessException e) {
                // Handled, but hopefully dead code  
                origProp=null;
            } catch (InvocationTargetException e) {
                // Single catch for obsolete java developers!
                origProp=null;
            } catch (NoSuchMethodException e) {
                // Single catch for obsolete java developers!
                origProp=null;
            }
            if (origProp != null 
                    && origProp.getClass().getPackage().toString().contains("domain")) {
                eagerize(origProp, visitedBeans);
            }
            if (origProp instanceof User){
                ((User) origProp).setRelatedNra(null);
                User u=(User) origProp;
                if (u.getRelatedMps()!=null)
                    u.getRelatedMps().clear();
                if (u.getRelatedDps()!=null)
                    u.getRelatedDps().clear();
            }
            if (origProp instanceof Collection) {               
                for (Object item : (Collection) origProp) {
                    if (item.getClass().getPackage().toString().contains("domain")){
                        eagerize(item, (ArrayList<String>) visitedBeans.clone());
                    }
                }
            }
        }
    }
}

根据您的需要修改它...您打电话的方法是&#34; eagerizeUnsafe&#34;。 YMMV,但是这应该是一个骗取ezrize懒惰初始化bean的所有集合的技巧。