读书人

Nutz DAO懒加载实业关联对象

发布时间: 2012-10-08 19:54:56 作者: rapoo

Nutz DAO懒加载实体关联对象

?

以前一直使用Hibernate,习惯了关联实体的懒加载。最近使用Nutz,里面没有提供懒加载的支持,于是乎自己扩展了一下Dao代码使其支持懒加载。这样用户在获取数据时就无需关心从dao抓取关联对象的问题了,调用POPO的getter方法时即可自动加载关联实体。下面就具体方案整理如下:
1. 定义一个名为LinkFieldGetterIntercepter的方法拦截器: 用于调用POJO的getter时自动加载关联对象。
2. 自定义一个EntityHolder: reloadEntity时创建实体代理类,添加第1条中定义的拦截器。并使用实体代理类在mappings中缓存实体。
3. 自定义一个org.nutz.dao.entity.Borning: 便于将ResultSet转换成POJO时,创建的是POJO的代理类实例,而不是POJO原始类实体。
4. 自定义一个EntityMaker: make方法中解析实体时setBorning(...)为第3条中定义的Borning对象。

下面是本人使用JPA作为POJO的annotation,扩展后的相关代码,如果直接使用Nutz annotation实现应该更简单。方法都是一样的。
1. LinkFieldGetterIntercepter:

public class LinkFieldGetterIntercepter extends AbstractMethodInterceptor {private static final Log log = Logs.getLog(LinkFieldGetterIntercepter.class);private Dao dao;private Link link;public LinkFieldGetterIntercepter(Dao dao, Link link) {this.dao = dao;this.link = link;}public Object afterInvoke(Object obj, Object returnObj, Method method, Object... args) {if (returnObj != null) {return returnObj;}String name = link.getOwnField().getName();dao.fetchLinks(obj, name);returnObj = Mirrors.getValue(obj, name);return returnObj;}}

?

?

2. EntityHolder

public class DemsyEntityHolder {private Dao dao;// Dao 对象private EntityMaker maker;private Map<Class<?>, Entity<?>> mappings;// <AOP代理类,实体>private Map<Class, Class> agentClassMap;// <实体类,AOP代理类>public DemsyEntityHolder(DemsyNutDao dao) {this.dao = dao;this.maker = dao.getEntityMaker();mappings = new HashMap<Class<?>, Entity<?>>();agentClassMap = new HashMap<Class, Class>();}public <T> Entity<T> getEntity(Class<T> classOfT) {// 转换成AOP代理类if (!Mirrors.isAgent(classOfT)) {classOfT = agentClassMap.get(classOfT);}if (classOfT == null) {return null;}return (Entity<T>) mappings.get(classOfT);}@SuppressWarnings("unchecked")public <T> Entity<T> reloadEntity(Class<T> classOfT, boolean autoCreateTable) {JPAEntity<?> entity = (JPAEntity<?>) maker.make(null, null, classOfT);// 缓存实体mappings.put(agentClass(entity), entity);return (Entity<T>) entity;}// 创建代理类private Class agentClass(JPAEntity entity) {Class cls = entity.getType();if (Mirrors.isAgent(cls)) {return cls;}ClassAgent classAgent = new AsmClassAgent();List<Link> links = entity.getLinks(null);if (links != null) {for (Link link : links) {String fieldName = link.getOwnField().getName();fieldName = fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);classAgent.addInterceptor(MethodMatcherFactory.matcher("get" + fieldName),new LinkFieldGetterIntercepter(dao, link));}}Class agentClass = classAgent.define(new DefaultClassDefiner(), cls);entity.setAgentMirror(Mirror.me(agentClass));this.agentClassMap.put(cls, agentClass);return agentClass;}public int count() {return mappings.size();}}

?

3 Borning:

class DemsyBorning implements Borning {JPAEntity entity;DemsyBorning(JPAEntity entity) {this.entity = entity;}/** * 创建实体代理实例 *  * @return * @throws Exception */public Object create() throws Exception {//创建代理类的实例,而不是原始类的实例return entity.getAgentMirror().born();}public Object born(ResultSet rs, FieldMatcher fm) throws Exception {Object obj = create();Iterator<EntityField> it = entity.fields().iterator();while (it.hasNext()) {EntityField ef = it.next();if (null == fm || fm.match(ef.getField().getName()))ef.fillValue(obj, rs);}return obj;}}

?

?

4 EntityMaker:

?

......public Entity<?> make(DatabaseMeta db, Connection conn, Class<?> type) {......// Borningentity.setBorning(new DemsyBorning(entity));......
挺不错的.

读书人网 >软件架构设计

热点推荐