在中大型业务系统中, 常常需要从数据库中查询某个实体对象。 在进行处理之前, 必须先检测该实体是否存在,以增强系统的健壮性。 不过, 检测代码充斥在主业务流程中又会大大降低业务逻辑的清晰性, 最好集中起来进行管理。 因此,编写了一个类来做这个事情, 只需要一行调用就可以完成相应实体对象的检测。
美中不足的一点是, 打 log 的位置发生变化了。由于打 log 的主要目标是为了便于调试和定位错误位置, 为了补偿, 一种办法是调用方法时根据具体语境传入自定义的错误消息, 根据错误消息可以定位错误位置; 另一种办法是, 如果不希望每次调用都使用不同的自定义错误消息, 使用 log.error(bizEx.getMessage(), bizEx) 打印异常栈信息, 也可以获取到抛出错误的位置。代码如下(可运行):
使用方法:
package patterns.singleton.demo;import junit.framework.Assert;import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory;import patterns.singleton.demo.exception.BizException; import patterns.singleton.demo.exception.IErrorCode; import patterns.singleton.demo.exception.NotExistErrorCode; import patterns.singleton.demo.exception.ResultSet; import patterns.singleton.demo.model.Order; import patterns.singleton.demo.model.Product; import patterns.singleton.demo.CheckEntityExistManager.EntityChecker; import static patterns.singleton.demo.CheckEntityExistManager.checkEntity;public class EntityExistCheckTester {private static final Log log = LogFactory.getLog(EntityExistCheckTester.class);public static void main(String[] args) throws BizException {ResultSet result = demo();Assert.assertEquals(NotExistErrorCode.ERROR_ORDER_NOT_EXIST.getCode(), result.getCode());Assert.assertEquals(NotExistErrorCode.ERROR_ORDER_NOT_EXIST.getMsg(), result.getMsg());ResultSet res2 = demo2();Assert.assertEquals(IErrorCode.SUCCESSFUL.getCode(), res2.getCode());Assert.assertEquals(IErrorCode.SUCCESSFUL.getMsg(), res2.getMsg());}public static ResultSet demo() {try {// Not Need type casting Order order = checkEntity(EntityChecker.ORDER_ID_CHECK, "123", "user-defined msg: order not exist when creating");System.out.println(order);return new ResultSet(IErrorCode.SUCCESSFUL);} catch (BizException bizEx) {log.error(bizEx.getMessage(), bizEx);return new ResultSet(bizEx.getErrorCode());} catch (Exception ex) {log.error(ex);return new ResultSet(IErrorCode.FAILED);}}public static ResultSet demo2() {try {Product p = checkEntity(EntityChecker.PRODUCT_NAME_CHECK, "God");System.out.println(p);return new ResultSet(IErrorCode.SUCCESSFUL);} catch (BizException bizEx) {log.error(bizEx.getMessage(), bizEx);return new ResultSet(bizEx.getErrorCode());} catch (Exception ex) {log.error(ex);return new ResultSet(IErrorCode.FAILED);}}}
实体存在性集中检测类: CheckEntityExistManager:
package patterns.singleton.demo;import java.util.HashMap; import java.util.Map;import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory;import patterns.singleton.demo.exception.BizException; import patterns.singleton.demo.exception.IErrorCode; import patterns.singleton.demo.exception.NotExistErrorCode; import patterns.singleton.demo.model.Order; import patterns.singleton.demo.model.Product;public class CheckEntityExistManager {private static final Log log = LogFactory.getLog(CheckEntityExistManager.class);private static CheckEntityExistManager checkEntityMgr = getInstance();private CheckEntityExistManager() {}private static CheckEntityExistManager getInstance() {if (checkEntityMgr == null) {checkEntityMgr = new CheckEntityExistManager();}return checkEntityMgr;}interface ICheckEntityExist<T> {T checkEntityExist(String entityValue, String msg) throws BizException;}private static ICheckEntityExist<Order> orderIdChecker = checkEntityMgr.new CheckOrderExist();private static ICheckEntityExist<Product> productChecker = checkEntityMgr.new CheckProductExist();public enum EntityChecker {ORDER_ID_CHECK(orderIdChecker, NotExistErrorCode.ERROR_ORDER_NOT_EXIST),PRODUCT_NAME_CHECK(productChecker, NotExistErrorCode.ERROR_PRODUCT_NOT_EXIST);EntityChecker(ICheckEntityExist<?> entityChecker, IErrorCode errorCode) {this.entityChecker = entityChecker;this.errorCode = errorCode;}private static Map<String, IErrorCode> errorMap = new HashMap<String, IErrorCode>();static {for (EntityChecker entityChecker: EntityChecker.values()) {ICheckEntityExist<?> checker = entityChecker.getEntityChecker();errorMap.put(checker.getClass().getSimpleName(), entityChecker.getErrorCode());}}private static IErrorCode getErrorCode(String checkClassSimpleName) {return errorMap.get(checkClassSimpleName);}private ICheckEntityExist<?> entityChecker;private IErrorCode errorCode;public ICheckEntityExist<?> getEntityChecker() {return entityChecker;}public void setEntityChecker(ICheckEntityExist<?> entityChecker) {this.entityChecker = entityChecker;}public IErrorCode getErrorCode() {return errorCode;}public void setErrorCode(IErrorCode errorCode) {this.errorCode = errorCode;}}// may using spring bean autowired in actual projectsprivate OrderService orderService = new OrderService() {public Order queryOrderByOrderId(int orderId) {return null;}};private ProductService productService = new ProductService() {public Product queryProductByName(String productName) {Product p = new Product();p.setProductId(1);p.setName("God");p.setDesc("Aman");return p;}};class CheckOrderExist implements ICheckEntityExist<Order> {public Order checkEntityExist(String orderId, String msg) throws BizException {IErrorCode errorCode = EntityChecker.getErrorCode(CheckOrderExist.class.getSimpleName());String message = (msg == null ? errorCode.getMsg() : msg);Order order = orderService.queryOrderByOrderId(Integer.parseInt(orderId));return CheckEntityExistManager.throwexOrReturn(order, message, errorCode);}}class CheckProductExist implements ICheckEntityExist<Product> {public Product checkEntityExist(String productName, String msg) throws BizException {IErrorCode errorCode = EntityChecker.getErrorCode(CheckProductExist.class.getSimpleName());String message = (msg == null ? errorCode.getMsg() : msg);Product p = productService.queryProductByName(productName);return CheckEntityExistManager.throwexOrReturn(p, message, errorCode);}}public static <T> T throwexOrReturn(T entity, String message, IErrorCode errorCode) throws BizException {if (entity == null) {log.error(message);throw new BizException(errorCode);}return entity;}public static <T> T checkEntity(EntityChecker entityChecker, String entityValue, String customMsg) throws BizException {ICheckEntityExist<T> checker = (ICheckEntityExist<T>) entityChecker.getEntityChecker();return checker.checkEntityExist(entityValue, customMsg);}public static <T> T checkEntity(EntityChecker entityChecker, String entityValue) throws BizException {ICheckEntityExist<T> checker = (ICheckEntityExist<T>) entityChecker.getEntityChecker();return checker.checkEntityExist(entityValue, null);}}interface OrderService {Order queryOrderByOrderId(int orderId); }interface ProductService {Product queryProductByName(String productName); }
异常、错误代码相关的类:
package patterns.singleton.demo.exception;public class BizException extends RuntimeException {private int code;private String msg;private IErrorCode errorCode;public BizException(String msg) {super(msg);}public BizException(IErrorCode error) {this.errorCode = error;this.code = error.getCode();this.msg = error.getMsg();}public BizException(Throwable cause) {super(cause);}public IErrorCode getErrorCode() {return errorCode;}}
package patterns.singleton.demo.exception;public interface IErrorCode {int getCode();String getMsg();public IErrorCode SUCCESSFUL = new IErrorCode() {public int getCode() {return 200;}public String getMsg() {return "successful";}};public IErrorCode FAILED = new IErrorCode() {public int getCode() {return 0;}public String getMsg() {return "failed";}};}
package patterns.singleton.demo.exception;public enum NotExistErrorCode implements IErrorCode {ERROR_ORDER_NOT_EXIST(-180, "order not exist"),ERROR_PRODUCT_NOT_EXIST(-190, "product not exist");private int code;private String msg;NotExistErrorCode(int code, String msg) {this.code = code;this.msg = msg;}public int getCode() {return this.code;}public String getMsg() {return this.msg;}}
package patterns.singleton.demo.exception;public class ResultSet<T> {public static final ResultSet SUCCESS = new ResultSet();private int code;private String msg;private T data;public ResultSet() {this.code = 200;this.msg = "success";}public ResultSet(T data) {this();this.data = data;}public ResultSet(int code, String msg) {this.code = code;this.msg = msg;}public ResultSet(IErrorCode ex) {this(ex.getCode(), ex.getMsg());}public int getCode() {return code;}public void setCode(int code) {this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public T getData() {return data;}public void setData(T data) {this.data = data;}}
数据对象:
package patterns.singleton.demo.model;public class Order {private Integer orderId;private String productName;private int account;public Integer getOrderId() {return orderId;}public void setOrderId(Integer orderId) {this.orderId = orderId;}public String getProductName() {return productName;}public void setProductName(String productName) {this.productName = productName;}public int getAccount() {return account;}public void setAccount(int account) {this.account = account;}}
package patterns.singleton.demo.model;public class Product {private Integer productId;private String name;private String desc;public Integer getProductId() {return productId;}public void setProductId(Integer productId) {this.productId = productId;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getDesc() {return desc;}public void setDesc(String desc) {this.desc = desc;}}