package org.nutz.dao; import java.util.Map; import org.nutz.lang.Lang; import org.nutz.lang.Mirror; import org.nutz.lang.segment.Segment; import org.nutz.lang.util.Context; import org.nutz.log.Log; import org.nutz.log.Logs; /** * 将一个参考对象存入 ThreadLocal * <p> * Nutz.Dao 将在构造 SQL 时,参考这个对象。如何参考,请参看 '@Table' 关于 “动态表名的赋值规则” 的描述 * * @author zozoh(zozohtnt@gmail.com) */ public class TableName { private static final Log log = Logs.get(); private static final ThreadLocal<Object> object = new ThreadLocal<Object>(); /** * 代码模板,这个模板保证了,在 atom 中运行的 POJO 的动态表名,都会被参考对象所影响 * * @param refer * 参考对象 * @param atom * 你的业务逻辑 */ public static void run(Object refer, Runnable atom) { if (null != atom) { if (log.isTraceEnabled()) log.tracef("TableName.run: [%s]->[%s]", object, object.get()); Object old = get(); set(refer); try { atom.run(); } catch (Exception e) { throw Lang.wrapThrow(e); } finally { set(old); if (log.isTraceEnabled()) log.tracef("TableName.finally: [%s]->[%s]", object, object.get()); } } } /** * @return 当前线程中的动态表名参考对象 */ public static Object get() { return object.get(); } /** * 为当前线程设置动态表名参考对象 * * @param obj * 参考对象 * @return 旧的动态表名参考对象 */ public static Object set(Object obj) { Object re = get(); object.set(obj); return re; } /** * 清除当前线程的动态表名参考对象 */ public static void clear() { set(null); } /** * 根据当前线程的参考对象,渲染一个动态表名 * * @param tableName * 动态表名 * @return 渲染后的表名 */ public static String render(Segment tableName) { Object obj = get(); if (null == obj || !tableName.hasKey()) return tableName.toString(); Context context = Lang.context(); if (isPrimitive(obj)) { for (String key : tableName.keys()) context.set(key, obj); } else if (obj instanceof Context) { for (String key : tableName.keys()) context.set(key, ((Context) obj).get(key)); } else if (obj instanceof Map<?, ?>) { for (String key : tableName.keys()) context.set(key, ((Map<?, ?>) obj).get(key)); } else { Mirror<?> mirror = Mirror.me(obj); for (String key : tableName.keys()) context.set(key, mirror.getValue(obj, key)); } return tableName.render(context).toString(); } public static boolean isPrimitive(Object obj) { return obj instanceof CharSequence || obj instanceof Number || obj.getClass().isPrimitive(); } }