相信大部分用过Ext的GridPanel显示数据的朋友都遇到过外键数据的问题,首先是转换格式,将数据库里查出来的List集合要转换为JSON格式,如果只是用
JSONObject json = new JSONObject();
JSONArray dataArray = JSONArray.fromObject(list);
如果list中的数据都是普通数据类型的那能正常转换,但很少这种情况,大部分的数据都存在外键的数据,比如有个News类,他可能会有个发布人User的外键,那么用以上的方法转换是不行,将会出现死循环(我去了解到JSON它是这么一种机制,将数据拆分,一致拆分到全都是基本数据类型位置,比如,一个list存放着多个News数据,它是首先将list拆分成多个News,然后将News的多个属性都拆分出来,里面有个User对象,又得再拆分!问题就出现在这了,User里面又有一个News的集合,News里面又有User,因此导致死循环了);当我遇到这个问题时,我到网上搜了下,发现的解决方案是过滤掉外键对象的数据,以下是我抽出出来写在2个类里面;
/**
* 转换为JSON格式数据
*/
public final class Convert {
/**
* @param properties需要过滤的属性名字数组(String [])
* @param data 需要转换格式的数据集合(List)
* @param jsonName 存 在json 中的名字,用于页面GridPanel的store的root属性调用
* @return 转换为JSONObject格式后的数据
*/
public final static JSONObject getJSON(String[] properties, List data, String jsonName) {
JSONObject json = new JSONObject();
JsonConfig config = new JsonConfig();
config.setIgnoreDefaultExcludes(false);
config.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT);
config.registerJsonValueProcessor(Date.class, new DateJsonValueProcessor("yyyy/MM/dd")); // 处理日期
config.setExcludes(properties);
json.put(jsonName, JSONSerializer.toJSON(data, config));
return json;
}
}
/**
* 转换日期格式
*/
public class DateJsonValueProcessor implements JsonValueProcessor {
public static final String DEFAULT_DATE_PATTERN = "yyyy/MM/dd";
private DateFormat dateFormat;
public DateJsonValueProcessor(String datePattern) {
try {
dateFormat = new SimpleDateFormat(datePattern);
} catch (Exception ex) {
dateFormat = new SimpleDateFormat(DEFAULT_DATE_PATTERN);
}
}
public Object processArrayValue(Object value, JsonConfig jsonConfig) {
return process(value);
}
public Object processObjectValue(String key, Object value,
JsonConfig jsonConfig) {
return process(value);
}
private Object process(Object value) {
if (value == null || "".equals(value)){
return "";
} else {
return dateFormat.format((java.util.Date) value);
}
}
}
在Action或其他地方调用:
将需要转换格式的newsList传入,把News中的User外键过滤掉(防止无法解析,造成死循环),存如json中的名字为newsList;(过滤掉的数据将无法再GridPanel中使用)
JSONObject json = Convert.getJSON(new String[] {"User"}, newsList, "newsList");
然后编写好GridPanel的store属性的root为存在json中的名字newsList就OK了,数据正常显示;
但是经常情况下我们需要把外键的数据也给显示出来,比如刚才的新闻信息,有可能需要把新闻的发布人User给显示出来,那么User就不能过滤掉了,对于这个问题我百度、google了好久,后来不知道是哪里突然给了我灵感,居然User中有News的集合JSON会往下解析,那为何不把它给清空掉呢 ?因此我使用了以下解决方案:
// 迭代list将News里面User的所有的News集合清空
for (int i = 0; i < newsList.size(); i++) {
User user = ((News) newsList.get(i)).getUser();
user.setNews(null);
}
那么调用刚才写好的转换的方法就变成:
JSONObject json = Convert.getJSON(new String[] {}, newsList, "newsList");
不需要过滤user属性(或者写个getJSON的重载方法,将第一个参数去掉)
在脚本中的GridPanel的不需要做很大修改,只需要加上要显示的数据列,
ColumnModel中加上这一列
{ header: "发布人", dataIndex: "user.userName", sortable: true}
fields里也加上:"user.userName" 那么就OK 了,数据外键数据就显示出来了```
附:
本人是Ext初学者,实在是找不到解决方案,就用了这种方法,不知道可不可行,个人觉得如果数据量不大的话应该可以考虑,望各位高手指点指点...