0

我有一个具有嵌套属性的对象列表,并且在层次结构的底部,每个对象都有一个 CommonsMultipartFile 属性。

一个文件夹有一个Requisites列表,每个 Requisites 都有一个页面列表

这些是 bean 定义,每个都在自己的文件中:

Page {
    private CommonsMultipartFile attributes;
    // Getter & Setter        
}

Requisite {       
    private List<Page> pages;
    // Other properties and Getters & Setters
}

Folder {
    private List<Requisite> requisites;
    // Getter & Setter
}

然后我在 Controller 方法中将一个 Folder 对象添加到我的 modelMap 中:

@RequestMapping(value = "loadFiles", method = RequestMethod.GET)
public String initFiles(ModelMap model, HttpServletRequest request) {
    Folder folder = new Folder();
    folder.setRequisites(requisitesModel.getRequisitesFromDB());
    model.addAttribute("folder", folder);
    return "loadFiles";
}

此时,模型属性“文件夹”有一个 Requisite 对象列表,其中初始化了各种属性,但是页面 (List <Page>) 在所有这些对象中都是空的。这种方法工作正常,允许用户加载一堆文件,并且发布请求按预期工作。

然后我添加了一个处理 MaxUploadSizeExceededException 的方法,并在resolveException方法中复制了上述控制器的行为。这是在总文件大小超过给定阈值时将用户重定向到相同的表单。

这是 resolveException 方法的定义:

public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse
    response, Object handler, Exception exception) {
    ModelMap model = new ModelMap();
    Folder folder = new Folder();
    folder.setRequisites(requisitesModel.getRequisitesFromDB());
    model.addAttribute("error", "The files exceed the maximum filesize");
    model.addAttribute("folder", folder);
    return new ModelAndView("loadFiles", model);
}

问题是,在这一个中,autoGrowNestedPaths 不起作用,因为立即抛出bean 类 [mypackage.Folder] 的 Invalid property 'requisites[0].pages[0]':无法访问索引属性路径'pages 中引用的属性的索引值[0]':返回 null

我的理解是,默认情况下,spring 会为所有 Collection 类型自动增长嵌套路径,即使不使用 LazyList 或 AutopopulatingList。我的理解错了吗?我需要添加其他东西吗?

4

2 回答 2

2

Jorge,我自己解决了这个问题。

WebDataBinder默认自动增长嵌套路径;这包括收藏。

但有趣的是,这取决于从属性 getter 方法获取 Collection 的“通用类型”。它使用反射——调用Method.getGenericReturnType(),它返回一个 java.lang.reflect.Type。

如果它有效,你会得到一个带有集合元素类型的 java.lang.reflect.ParameterizedType 来增长;如果没有,Spring 将获得一个“空”元素类型并且不会自动增长。

org.springframework.beans.BeanWrapperImpl.growCollectionIfNecessary()

在我的情况下,发现 Hibernate 代理(子类)没有必要的泛型类型和方法签名信息..即使此信息在实体类上(直接使用时!)

我在我的表单控制器“loadEntity”设置中取消了实体的代理,并且就像下雨一样。(有时,在 Hibernate 应用程序中,取消代理是有用且必要的,其他代理检查、比较和操作也是如此。)

代码示例:

public static <T>  T deproxy (T obj) {
    if (obj == null)
        return obj;
    if (obj instanceof HibernateProxy) {
        // Unwrap Proxy;
        //      -- loading, if necessary.
        HibernateProxy proxy = (HibernateProxy) obj;
        LazyInitializer li = proxy.getHibernateLazyInitializer();
        return (T)  li.getImplementation();
    } 
    return obj;
}

public static boolean isProxy (Object obj) {
    if (obj instanceof HibernateProxy)
        return true;
    return false;
}

public static boolean isSame (Object o1, Object o2) {
    if (o1 == o2)
        return true;
    if (o1 == null || o2 == null) 
        return false;
    Object d1 = deproxy(o1);
    Object d2 = deproxy(o2);
    if (d1 == d2)
        return true;
    return false;
}

public static Class getClassWithoutInitializingProxy (Object obj) {
    if (obj instanceof HibernateProxy) {
        HibernateProxy proxy = (HibernateProxy) obj;
        LazyInitializer li = proxy.getHibernateLazyInitializer();
        return li.getPersistentClass();
    } 
    // Not a Proxy.
    return obj.getClass();
}

希望这可以帮助您解决问题..甚至给我一个赞成票!

于 2013-03-14T11:09:35.707 回答
0

来自BeanWrapper javadoc

setAutoGrowNestedPaths

无效 setAutoGrowNestedPaths(布尔 autoGrowNestedPaths)

设置此 BeanWrapper 是否应尝试“自动增长”包含空值的嵌套路径。如果为“true”,则将使用默认对象值填充空路径位置并进行遍历,而不是导致 NullValueInNestedPathException。打开此标志还可以在访问越界索引时启用集合元素的自动增长。

在普通 BeanWrapper 上默认为“false”。

所以不,BeanWrapperImpl默认情况下不会自动增长列表的嵌套路径(假设您使用的是 spring 3)。就像您在帖子中提到的那样,您可以使用自动填充或惰性列表来解决此问题。您还可以使用 initbinder 将 autogrowNestedPaths 属性显式设置为 true。

于 2012-08-23T05:25:27.233 回答