商品有多张商品图片,一对多关系。
项目中采用单表设计,沿用太久,原因就不追溯了,也没有动改它结构的念头。
忽略其它字段,product表包含img1Path、img2Path、img3Path……img10Path,对应的product实体类也包含这10个成员变量。(path即图片链接,字符串)
目前img1Path到img10Path都可能为空,需要遍历;也没有采用数据传输对象,用map返回。
所以页面需要带一张图片的商品时,原本业务代码大概如下:
Product p = productService.get(productId);
Map<String, Object> pMap = new HashMap<String, Object>();
pMap.put("name", p.getName());
// ……其它字段
pMap.put("imgPath", p.getImg1Path() != null ? p.getImg1Path() :
p.getImg2Path() != null ? p.getImg2Path() :
p.getImg3Path() != null ? p.getImg3Path() :
p.getImg4Path() != null ? p.getImg4Path() :
p.getImg5Path() != null ? p.getImg5Path() :
p.getImg6Path() != null ? p.getImg6Path() :
p.getImg7Path() != null ? p.getImg7Path() :
p.getImg8Path() != null ? p.getImg8Path() :
p.getImg9Path() != null ? p.getImg9Path() :
p.getImg10Path() != null ? p.getImg10Path() : null);
这样复用性差,我把抽取getImgPath(Product product)方法到service层:
public String getImgPath(p) {
return p.getImg1Path() != null ? p.getImg1Path() :
p.getImg2Path() != null ? p.getImg2Path() :
p.getImg3Path() != null ? p.getImg3Path() :
p.getImg4Path() != null ? p.getImg4Path() :
p.getImg5Path() != null ? p.getImg5Path() :
p.getImg6Path() != null ? p.getImg6Path() :
p.getImg7Path() != null ? p.getImg7Path() :
p.getImg8Path() != null ? p.getImg8Path() :
p.getImg9Path() != null ? p.getImg9Path() :
p.getImg10Path() != null ? p.getImg10Path() : null;
}
上面的业务代码可以改写为:
Product p = productService.get(productId);
Map<String, Object> pMap = new HashMap<String, Object>();
pMap.put("name", p.getName());
// ……其它字段
pMap.put("imgPath", productService.getImgPath(p));
有些字段字段通过实体类的方法获取,有些通过业务层的方法获取,不优雅。
其实能不能这样做,在product实体类中增加一个成员变量imgPath(数据表没有与之对应的imgPath字段)。
该成员变量无set方法,有get方法,如下:
public class Product {
private String img1Path;
// ……
private String img10Path;
private String imgPath;
public String getImgPath() {
this.imgPath = this.img1Path != null ? this.img1Path :
this.i2Path != null ? this.img2Path :
this.img3Path != null ? this.img3Path :
this.img4Path != null ? this.img4Path :
this.img5Path != null ? this.img5Path :
this.img6Path != null ? this.img6Path :
this.img7Path != null ? this.img7Path :
this.img8Path != null ? this.img8Path :
this.img9Path != null ? this.img9Path :
this.img10Path != null ? this.img10Path : null;
return this.imgPath;
}
}
上面的业务代码可以改写为:
Product p = productService.get(productId);
Map<String, Object> pMap = new HashMap<String, Object>();
pMap.put("name", p.getName());
// ……其它字段
pMap.put("imgPath", p.getImgPath());
甚至这个pMap也不封装了,直接返回p对象,模板引擎通过p.imgPath获取这个一个图片路径(突然想到,自己先去试一下)。
实体类这样写,是否更方便、合理?
验证了一下上面突如其来的猜想,结果如下:
public class Product {
private String img1Path;
// ……
private String img10Path;
public String getImgPath() {
return this.img1Path != null ? this.img1Path :
this.i2Path != null ? this.img2Path :
this.img3Path != null ? this.img3Path :
this.img4Path != null ? this.img4Path :
this.img5Path != null ? this.img5Path :
this.img6Path != null ? this.img6Path :
this.img7Path != null ? this.img7Path :
this.img8Path != null ? this.img8Path :
this.img9Path != null ? this.img9Path :
this.img10Path != null ? this.img10Path : null;
}
}
即不需要添加字段,可以直接添加一个get方法,方法名与本来想添加的字段字段名一致。
例如字段为:xxXxx,则添加的方法为:getXxXxx()。
后台把product放到json里返回到js(项目用的是AvalonJS 1.5),js可以通过product.xxXxx直接拿到数据。这跟之前用过的freemarker类似,.xxXxx取值调用的是getXxXxx()方法。