深入浅出设计模式(十):15.迭代器模式(Iterator) 16.模版方法模式(TemplateMethod)

15.迭代器模式(Iterator)

在软件开发中,经常需要将某一类对象放在一个集合里,或者放在容器里,这个时候通常需要对集合或容器里的对象进行访问,很明显,对集合或容器里对象的访问必须涉及遍历,这就是迭代器模式。

哪里会用到迭代器模式

在电子商城的网站开发中,经常会有一个产品的列表展示,经常会使用到循环进行处理,从而将产品一个一个地展示出来。在网站浏览新闻时,各种类型的新闻也是一条一条显示在界面上的,这种类型的展示都需要使用迭代器。

迭代器模式的实现原理

迭代器模式就是提供了一种方法顺序访问一个聚合对象中各个元素,而又不需暴露该对象的内部标识,迭代器模式分离了集合对象的遍历行为,抽象出一个迭代器类来负责,这样既可以做到不暴露集合的内部结构,又可以让外部代码透明地访问集合内部的数据。

这里写图片描述

迭代器模式在Java中的具体实现原理

Iterator

package java.util;

public interface Iterator<E> {
    boolean hasNext();
    E next();
    void remove();
}

Map

package java.util;

public interface Map<K, V> {

    int size();

    boolean isEmpty();

    boolean containsKey(Object key);

    boolean containsValue(Object value);

    V get(Object key);

    V put(K key, V value);

    V remove(Object key);

    void putAll(Map<? extends K, ? extends V> m);

    void clear();

    Set<K> keySet();

    Collection<V> values();

    Set<Map.Entry<K, V>> entrySet();

    interface Entry<K, V> {

        K getKey();

        V getValue();

        V setValue(V value);

        boolean equals(Object o);

        int hashCode();
    }

    boolean equals(Object o);

    int hashCode();
}

Collection

package java.util;

public interface Collection<E> extends Iterable<E> {

    int size();

    boolean isEmpty();

    boolean contains(Object o);

    Iterator<E> iterator();

    Object[] toArray();

    <T> T[] toArray(T[] a);

    boolean add(E e);

    boolean remove(Object o);

    boolean containsAll(Collection<?> c);

    boolean addAll(Collection<? extends E> c);

    boolean removeAll(Collection<?> c);

    boolean retainAll(Collection<?> c);

    void clear();

    boolean equals(Object o);

    int hashCode();
}

List

package java.util;

public interface List<E> extends Collection<E> {

    int size();

    boolean isEmpty();

    boolean contains(Object o);

    Iterator<E> iterator();

    Object[] toArray();

    <T> T[] toArray(T[] a);

    boolean add(E e);

    boolean remove(Object o);

    boolean containsAll(Collection<?> c);

    boolean addAll(Collection<? extends E> c);

    boolean addAll(int index, Collection<? extends E> c);

    boolean removeAll(Collection<?> c);

    boolean retainAll(Collection<?> c);

    void clear();

    boolean equals(Object o);

    int hashCode();

    E get(int index);

    E set(int index, E element);

    void add(int index, E element);

    E remove(int index);

    int indexOf(Object o);

    int lastIndexOf(Object o);

    ListIterator<E> listIterator();

    ListIterator<E> listIterator(int index);

    List<E> subList(int fromIndex, int toIndex);
}

16.模版方法模式(TemplateMethod)

模版方法模式在程序开发中经常使用,目的就是定义一系列算法执行的顺序,而把具体算法的实现在子类中完成,在很多框架(比如Spring、JUnit)中都实现了模版方法模式。

哪里会使用到模版方法模式

比如新闻发布系统中,对于查看新闻的页面来说,该新闻的抬头、结尾都有一定的格式,变化的只是新闻的内容,通常情况下,开发人员会使用模版技术,将新闻的抬头和结尾都固定,只改变新闻的内容,这样能够极大提高开发效率。

再比如其后介绍的命令模式,它是将用户事先设定好的命令存储起来,然后在指定的时间里按照一定的顺序将命令取出来执行,可以看出,在实际的应用开发中,命令模式与职责链模式可以很好的结合起来,对于用户的命令,可以通过命令模式进行存储,然后通过职责链模式,再将命令按照一定的顺序进行执行。

拿前面策略模式的薪资例子为例(和策略模式很像,但模版模式规定了执行方法的顺序):
这里写图片描述

模版方法模式的实现原理

这里写图片描述

模版方法模式在JUnit中的使用

源码比较简单,模版方法模式主要体现在TestCase类的runBare()方法

模版方法模式在Servlet中的使用

在HttpServlet中有几个重要的方法,一个是doPost()方法,一个是doGet()方法,还有一个是Service()方法。

Servlet是由WebLogic之类的Servlet容器来调用处理器请求的,Servlet定义了一个处理模版,实现Servlet只需继承Servlet并实现doGet、doPost等方法即可。

HttpServlet

package javax.servlet.http;

import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.text.MessageFormat;
import java.util.Enumeration;
import java.util.ResourceBundle;
import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public abstract class HttpServlet extends GenericServlet implements
        Serializable {
    private static final String METHOD_DELETE = "DELETE";
    private static final String METHOD_HEAD = "HEAD";
    private static final String METHOD_GET = "GET";
    private static final String METHOD_OPTIONS = "OPTIONS";
    private static final String METHOD_POST = "POST";
    private static final String METHOD_PUT = "PUT";
    private static final String METHOD_TRACE = "TRACE";
    private static final String HEADER_IFMODSINCE = "If-Modified-Since";
    private static final String HEADER_LASTMOD = "Last-Modified";
    private static final String LSTRING_FILE = "javax.servlet.http.LocalStrings";
    private static ResourceBundle lStrings = ResourceBundle
            .getBundle("javax.servlet.http.LocalStrings");

    // doGet方法
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        String protocol = req.getProtocol();
        String msg = lStrings.getString("http.method_get_not_supported");
        if (protocol.endsWith("1.1")) {
            resp.sendError(405, msg);
        } else {
            resp.sendError(400, msg);
        }
    }

    protected long getLastModified(HttpServletRequest req) {
        return -1L;
    }

    // doHead方法
    protected void doHead(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        NoBodyResponse response = new NoBodyResponse(resp);

        doGet(req, response);
        response.setContentLength();
    }

    // doPost方法
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        String protocol = req.getProtocol();
        String msg = lStrings.getString("http.method_post_not_supported");
        if (protocol.endsWith("1.1")) {
            resp.sendError(405, msg);
        } else {
            resp.sendError(400, msg);
        }
    }

    // doPut方法
    protected void doPut(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        String protocol = req.getProtocol();
        String msg = lStrings.getString("http.method_put_not_supported");
        if (protocol.endsWith("1.1")) {
            resp.sendError(405, msg);
        } else {
            resp.sendError(400, msg);
        }
    }

    // doDelete方法
    protected void doDelete(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        String protocol = req.getProtocol();
        String msg = lStrings.getString("http.method_delete_not_supported");
        if (protocol.endsWith("1.1")) {
            resp.sendError(405, msg);
        } else {
            resp.sendError(400, msg);
        }
    }

    private static Method[] getAllDeclaredMethods(Class c) {
        if (c.equals(HttpServlet.class)) {
            return null;
        }
        Method[] parentMethods = getAllDeclaredMethods(c.getSuperclass());
        Method[] thisMethods = c.getDeclaredMethods();
        if ((parentMethods != null) && (parentMethods.length > 0)) {
            Method[] allMethods = new Method[parentMethods.length
                    + thisMethods.length];

            System.arraycopy(parentMethods, 0, allMethods, 0,
                    parentMethods.length);

            System.arraycopy(thisMethods, 0, allMethods, parentMethods.length,
                    thisMethods.length);

            thisMethods = allMethods;
        }
        return thisMethods;
    }

    // doOptions方法
    protected void doOptions(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        Method[] methods = getAllDeclaredMethods(getClass());

        boolean ALLOW_GET = false;
        boolean ALLOW_HEAD = false;
        boolean ALLOW_POST = false;
        boolean ALLOW_PUT = false;
        boolean ALLOW_DELETE = false;
        boolean ALLOW_TRACE = true;
        boolean ALLOW_OPTIONS = true;
        for (int i = 0; i < methods.length; i++) {
            Method m = methods[i];
            if (m.getName().equals("doGet")) {
                ALLOW_GET = true;
                ALLOW_HEAD = true;
            }
            if (m.getName().equals("doPost")) {
                ALLOW_POST = true;
            }
            if (m.getName().equals("doPut")) {
                ALLOW_PUT = true;
            }
            if (m.getName().equals("doDelete")) {
                ALLOW_DELETE = true;
            }
        }
        String allow = null;
        if ((ALLOW_GET) && (allow == null)) {
            allow = "GET";
        }
        if (ALLOW_HEAD) {
            if (allow == null) {
                allow = "HEAD";
            } else {
                allow = allow + ", HEAD";
            }
        }
        if (ALLOW_POST) {
            if (allow == null) {
                allow = "POST";
            } else {
                allow = allow + ", POST";
            }
        }
        if (ALLOW_PUT) {
            if (allow == null) {
                allow = "PUT";
            } else {
                allow = allow + ", PUT";
            }
        }
        if (ALLOW_DELETE) {
            if (allow == null) {
                allow = "DELETE";
            } else {
                allow = allow + ", DELETE";
            }
        }
        if (ALLOW_TRACE) {
            if (allow == null) {
                allow = "TRACE";
            } else {
                allow = allow + ", TRACE";
            }
        }
        if (ALLOW_OPTIONS) {
            if (allow == null) {
                allow = "OPTIONS";
            } else {
                allow = allow + ", OPTIONS";
            }
        }
        resp.setHeader("Allow", allow);
    }

    // 执行doTrace
    protected void doTrace(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        String CRLF = "\r\n";
        String responseString = "TRACE " + req.getRequestURI() + " "
                + req.getProtocol();

        Enumeration reqHeaderEnum = req.getHeaderNames();
        while (reqHeaderEnum.hasMoreElements()) {
            String headerName = (String) reqHeaderEnum.nextElement();
            responseString = responseString + CRLF + headerName + ": "
                    + req.getHeader(headerName);
        }
        responseString = responseString + CRLF;
        // 获取长度
        int responseLength = responseString.length();
        // 设定报头
        resp.setContentType("message/http");
        resp.setContentLength(responseLength);
        ServletOutputStream out = resp.getOutputStream();
        out.print(responseString);
        out.close();
    }

    // 在service里判断具体执行哪个方法
    protected void service(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        String method = req.getMethod();
        if (method.equals("GET")) {
            long lastModified = getLastModified(req);
            if (lastModified == -1L) {
                doGet(req, resp);
            } else {
                long ifModifiedSince = req.getDateHeader("If-Modified-Since");
                if (ifModifiedSince < lastModified / 1000L * 1000L) {
                    maybeSetLastModified(resp, lastModified);
                    doGet(req, resp);
                } else {
                    resp.setStatus(304);
                }
            }
        } else if (method.equals("HEAD")) {
            long lastModified = getLastModified(req);
            maybeSetLastModified(resp, lastModified);
            doHead(req, resp);
        } else if (method.equals("POST")) {
            doPost(req, resp);
        } else if (method.equals("PUT")) {
            doPut(req, resp);
        } else if (method.equals("DELETE")) {
            doDelete(req, resp);
        } else if (method.equals("OPTIONS")) {
            doOptions(req, resp);
        } else if (method.equals("TRACE")) {
            doTrace(req, resp);
        } else {
            String errMsg = lStrings.getString("http.method_not_implemented");
            Object[] errArgs = new Object[1];
            errArgs[0] = method;
            errMsg = MessageFormat.format(errMsg, errArgs);

            resp.sendError(501, errMsg);
        }
    }

    // 记录最后的修改状态
    private void maybeSetLastModified(HttpServletResponse resp,
            long lastModified) {
        if (resp.containsHeader("Last-Modified")) {
            return;
        }
        if (lastModified >= 0L) {
            resp.setDateHeader("Last-Modified", lastModified);
        }
    }

    // 都会执行service方法
    public void service(ServletRequest req, ServletResponse res)
            throws ServletException, IOException {
        try {
            HttpServletRequest request = (HttpServletRequest) req;
            response = (HttpServletResponse) res;
        } catch (ClassCastException e) {
            HttpServletResponse response;
            throw new ServletException("non-HTTP request or response");
        }
        HttpServletResponse response;
        HttpServletRequest request;
        service(request, response);
    }
}

模版方法模式在数据库的实际应用

注:以下Spring源码是Spring 3.2.16的,现在已经弃用了,不过可以看看了解一下模式

JpaTemplate

package org.springframework.orm.jpa;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceException;
import javax.persistence.Query;
import org.apache.commons.logging.Log;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;

@Deprecated
public class JpaTemplate extends JpaAccessor implements JpaOperations {
    private boolean exposeNativeEntityManager = false;

    public JpaTemplate() {
    }

    public JpaTemplate(EntityManagerFactory emf) {
        setEntityManagerFactory(emf);
        afterPropertiesSet();
    }

    public JpaTemplate(EntityManager em) {
        setEntityManager(em);
        afterPropertiesSet();
    }

    public void setExposeNativeEntityManager(boolean exposeNativeEntityManager) {
        this.exposeNativeEntityManager = exposeNativeEntityManager;
    }

    public boolean isExposeNativeEntityManager() {
        return this.exposeNativeEntityManager;
    }

    // 用于实现查询方法的回调
    public <T> T execute(JpaCallback<T> action) throws DataAccessException {
        return execute(action, isExposeNativeEntityManager());
    }

    // 查询方法
    public List executeFind(JpaCallback<?> action) throws DataAccessException {
        Object result = execute(action, isExposeNativeEntityManager());
        if (!(result instanceof List)) {
            throw new InvalidDataAccessApiUsageException(
                    "Result object returned from JpaCallback isn't a List: ["
                            + result + "]");
        }
        return (List) result;
    }

    // 执行回调
    public <T> T execute(JpaCallback<T> action,
            boolean exposeNativeEntityManager) throws DataAccessException {
        Assert.notNull(action, "Callback object must not be null");
        // 获取实体管理器
        EntityManager em = getEntityManager();
        boolean isNewEm = false;
        if (em == null) {
            em = getTransactionalEntityManager();
            if (em == null) {
                this.logger
                        .debug("Creating new EntityManager for JpaTemplate execution");
                em = createEntityManager();
                isNewEm = true;
            }
        }
        // 反射
        try {
            EntityManager emToExpose = exposeNativeEntityManager ? em
                    : createEntityManagerProxy(em);
            T result = action.doInJpa(emToExpose);
            flushIfNecessary(em, !isNewEm);
            return result;
        } catch (RuntimeException ex) {
            throw translateIfNecessary(ex);
        } finally {
            if (isNewEm) {
                this.logger
                        .debug("Closing new EntityManager after JPA template execution");
                EntityManagerFactoryUtils.closeEntityManager(em);
            }
        }
    }

    // 创建实体管理器的代理
    protected EntityManager createEntityManagerProxy(EntityManager em) {
        Class[] ifcs = null;
        EntityManagerFactory emf = getEntityManagerFactory();
        if ((emf instanceof EntityManagerFactoryInfo)) {
            Class entityManagerInterface = ((EntityManagerFactoryInfo) emf)
                    .getEntityManagerInterface();
            if (entityManagerInterface != null) {
                ifcs = new Class[] { entityManagerInterface };
            }
        }
        if (ifcs == null) {
            ifcs = ClassUtils.getAllInterfacesForClass(em.getClass());
        }
        return (EntityManager) Proxy.newProxyInstance(em.getClass()
                .getClassLoader(), ifcs, new CloseSuppressingInvocationHandler(
                em));
    }

    // 查询方法的具体实现
    public <T> T find(final Class<T> entityClass, final Object id)
            throws DataAccessException {
        execute(new JpaCallback() {
            public T doInJpa(EntityManager em) throws PersistenceException {
                return em.find(entityClass, id);
            }
        }, true);
    }

    // 查询方法
    public <T> T getReference(final Class<T> entityClass, final Object id)
            throws DataAccessException {
        execute(new JpaCallback() {
            public T doInJpa(EntityManager em) throws PersistenceException {
                return em.getReference(entityClass, id);
            }
        }, true);
    }

    public boolean contains(final Object entity) throws DataAccessException {
        ((Boolean) execute(new JpaCallback() {
            public Boolean doInJpa(EntityManager em)
                    throws PersistenceException {
                return Boolean.valueOf(em.contains(entity));
            }
        }, true)).booleanValue();
    }

    // 刷新方法的具体实现
    public void refresh(final Object entity) throws DataAccessException {
        execute(new JpaCallback() {
            public Object doInJpa(EntityManager em) throws PersistenceException {
                em.refresh(entity);
                return null;
            }
        }, true);
    }

    // 保存方法的具体实现
    public void persist(final Object entity) throws DataAccessException {
        execute(new JpaCallback() {
            public Object doInJpa(EntityManager em) throws PersistenceException {
                em.persist(entity);
                return null;
            }
        }, true);
    }

    // 更新方法的具体实现
    public <T> T merge(final T entity) throws DataAccessException {
        execute(new JpaCallback() {
            public T doInJpa(EntityManager em) throws PersistenceException {
                return em.merge(entity);
            }
        }, true);
    }

    // 删除方法的具体实现
    public void remove(final Object entity) throws DataAccessException {
        execute(new JpaCallback() {
            public Object doInJpa(EntityManager em) throws PersistenceException {
                em.remove(entity);
                return null;
            }
        }, true);
    }

    public void flush() throws DataAccessException {
        execute(new JpaCallback() {
            public Object doInJpa(EntityManager em) throws PersistenceException {
                em.flush();
                return null;
            }
        }, true);
    }

    // 查询方法
    public List find(String queryString) throws DataAccessException {
        return find(queryString, (Object[]) null);
    }

    // 返回多笔查询结果
    public List find(final String queryString, final Object... values) throws DataAccessException
    {
        (List)execute(new JpaCallback()
        {
            public List doInJpa(EntityManager em) throws PersistenceException
            {
                Query queryObject = em.createQuery(queryString);
                JpaTemplate.this.prepareQuery(queryObject);
                if (values != null) {
                    for (int i = 0; i < values.length; i++) {
                        queryObject.setParameter(i + 1, values[i]);
                    }
                }
                return queryObject.getResultList();
            }
        });
    }

    // 根据名称和实体类查询
    public List findByNamedParams(final String queryString, final Map<String, ?> params)
    throws DataAccessException
  {
    (List)execute(new JpaCallback()
    {
      public List doInJpa(EntityManager em)
        throws PersistenceException
      {
        Query queryObject = em.createQuery(queryString);
        JpaTemplate.this.prepareQuery(queryObject);
        if (params != null) {
          for (Map.Entry<String, ?> entry : params.entrySet()) {
            queryObject.setParameter((String)entry.getKey(), entry.getValue());
          }
        }
        return queryObject.getResultList();
      }
    });
  }

    public List findByNamedQuery(String queryName) throws DataAccessException {
        return findByNamedQuery(queryName, (Object[]) null);
    }

    public List findByNamedQuery(final String queryName, final Object... values)
    throws DataAccessException
  {
    (List)execute(new JpaCallback()
    {
      public List doInJpa(EntityManager em)
        throws PersistenceException
      {
        Query queryObject = em.createNamedQuery(queryName);
        JpaTemplate.this.prepareQuery(queryObject);
        if (values != null) {
          for (int i = 0; i < values.length; i++) {
            queryObject.setParameter(i + 1, values[i]);
          }
        }
        return queryObject.getResultList();
      }
    });
  }

    public List findByNamedQueryAndNamedParams(final String queryName, final Map<String, ?> params)
    throws DataAccessException
  {
    (List)execute(new JpaCallback()
    {
      public List doInJpa(EntityManager em)
        throws PersistenceException
      {
        Query queryObject = em.createNamedQuery(queryName);
        JpaTemplate.this.prepareQuery(queryObject);
        if (params != null) {
          for (Map.Entry<String, ?> entry : params.entrySet()) {
            queryObject.setParameter((String)entry.getKey(), entry.getValue());
          }
        }
        return queryObject.getResultList();
      }
    });
  }

    public void prepareQuery(Query query) {
        EntityManagerFactory emf = getEntityManagerFactory();
        if (emf != null) {
            EntityManagerFactoryUtils.applyTransactionTimeout(query,
                    getEntityManagerFactory());
        }
    }

    private class CloseSuppressingInvocationHandler implements
            InvocationHandler {
        private final EntityManager target;

        public CloseSuppressingInvocationHandler(EntityManager target) {
            this.target = target;
        }

        // java反射的具体应用
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            if (method.getName().equals("equals")) {
                return Boolean.valueOf(proxy == args[0]);
            }
            if (method.getName().equals("hashCode")) {
                return Integer.valueOf(System.identityHashCode(proxy));
            }
            if (method.getName().equals("close")) {
                return null;
            }
            try {
                Object retVal = method.invoke(this.target, args);
                if ((retVal instanceof Query)) {
                    JpaTemplate.this.prepareQuery((Query) retVal);
                }
                return retVal;
            } catch (InvocationTargetException ex) {
                throw ex.getTargetException();
            }
        }
    }
}

JdoTemplate

package org.springframework.orm.jdo;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collection;
import java.util.Map;
import javax.jdo.JDOException;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
import javax.jdo.Query;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;

@Deprecated
public class JdoTemplate extends JdoAccessor implements JdoOperations {
    private boolean allowCreate = true;
    private boolean exposeNativePersistenceManager = false;

    public JdoTemplate() {
    }

    public JdoTemplate(PersistenceManagerFactory pmf) {
        setPersistenceManagerFactory(pmf);
        afterPropertiesSet();
    }

    public JdoTemplate(PersistenceManagerFactory pmf, boolean allowCreate) {
        setPersistenceManagerFactory(pmf);
        setAllowCreate(allowCreate);
        afterPropertiesSet();
    }

    public void setAllowCreate(boolean allowCreate) {
        this.allowCreate = allowCreate;
    }

    public boolean isAllowCreate() {
        return this.allowCreate;
    }

    public void setExposeNativePersistenceManager(
            boolean exposeNativePersistenceManager) {
        this.exposeNativePersistenceManager = exposeNativePersistenceManager;
    }

    public boolean isExposeNativePersistenceManager() {
        return this.exposeNativePersistenceManager;
    }

    public <T> T execute(JdoCallback<T> action) throws DataAccessException {
        return execute(action, isExposeNativePersistenceManager());
    }

    public Collection executeFind(JdoCallback<?> action)
            throws DataAccessException {
        Object result = execute(action, isExposeNativePersistenceManager());
        if ((result != null) && (!(result instanceof Collection))) {
            throw new InvalidDataAccessApiUsageException(
                    "Result object returned from JdoCallback isn't a Collection: ["
                            + result + "]");
        }
        return (Collection) result;
    }

    public <T> T execute(JdoCallback<T> action,
            boolean exposeNativePersistenceManager) throws DataAccessException {
        Assert.notNull(action, "Callback object must not be null");

        PersistenceManager pm = PersistenceManagerFactoryUtils
                .getPersistenceManager(getPersistenceManagerFactory(),
                        isAllowCreate());

        boolean existingTransaction = TransactionSynchronizationManager
                .hasResource(getPersistenceManagerFactory());
        try {
            PersistenceManager pmToExpose = exposeNativePersistenceManager ? pm
                    : createPersistenceManagerProxy(pm);
            T result = action.doInJdo(pmToExpose);
            flushIfNecessary(pm, existingTransaction);
            return postProcessResult(result, pm, existingTransaction);
        } catch (JDOException ex) {
            throw convertJdoAccessException(ex);
        } catch (RuntimeException ex) {
            throw ex;
        } finally {
            PersistenceManagerFactoryUtils.releasePersistenceManager(pm,
                    getPersistenceManagerFactory());
        }
    }

    protected PersistenceManager createPersistenceManagerProxy(
            PersistenceManager pm) {
        Class[] ifcs = ClassUtils.getAllInterfacesForClass(pm.getClass(),
                getClass().getClassLoader());
        return (PersistenceManager) Proxy.newProxyInstance(pm.getClass()
                .getClassLoader(), ifcs, new CloseSuppressingInvocationHandler(
                pm));
    }

    protected <T> T postProcessResult(T result, PersistenceManager pm,
            boolean existingTransaction) {
        return result;
    }

    public Object getObjectById(final Object objectId)
            throws DataAccessException {
        execute(new JdoCallback() {
            public Object doInJdo(PersistenceManager pm) throws JDOException {
                return pm.getObjectById(objectId, true);
            }
        }, true);
    }

    public <T> T getObjectById(final Class<T> entityClass, final Object idValue)
            throws DataAccessException {
        execute(new JdoCallback() {
            public T doInJdo(PersistenceManager pm) throws JDOException {
                return pm.getObjectById(entityClass, idValue);
            }
        }, true);
    }

    public void evict(final Object entity) throws DataAccessException {
        execute(new JdoCallback() {
            public Object doInJdo(PersistenceManager pm) throws JDOException {
                pm.evict(entity);
                return null;
            }
        }, true);
    }

    public void evictAll(final Collection entities) throws DataAccessException {
        execute(new JdoCallback() {
            public Object doInJdo(PersistenceManager pm) throws JDOException {
                pm.evictAll(entities);
                return null;
            }
        }, true);
    }

    public void evictAll() throws DataAccessException {
        execute(new JdoCallback() {
            public Object doInJdo(PersistenceManager pm) throws JDOException {
                pm.evictAll();
                return null;
            }
        }, true);
    }

    public void refresh(final Object entity) throws DataAccessException {
        execute(new JdoCallback() {
            public Object doInJdo(PersistenceManager pm) throws JDOException {
                pm.refresh(entity);
                return null;
            }
        }, true);
    }

    public void refreshAll(final Collection entities)
            throws DataAccessException {
        execute(new JdoCallback() {
            public Object doInJdo(PersistenceManager pm) throws JDOException {
                pm.refreshAll(entities);
                return null;
            }
        }, true);
    }

    public void refreshAll() throws DataAccessException {
        execute(new JdoCallback() {
            public Object doInJdo(PersistenceManager pm) throws JDOException {
                pm.refreshAll();
                return null;
            }
        }, true);
    }

    public <T> T makePersistent(final T entity) throws DataAccessException {
        execute(new JdoCallback() {
            public T doInJdo(PersistenceManager pm) throws JDOException {
                return pm.makePersistent(entity);
            }
        }, true);
    }

    public <T> Collection<T> makePersistentAll(final Collection<T> entities)
    throws DataAccessException
  {
    (Collection)execute(new JdoCallback()
    {
      public Collection<T> doInJdo(PersistenceManager pm)
        throws JDOException
      {
        return pm.makePersistentAll(entities);
      }
    }, true);
  }

    public void deletePersistent(final Object entity)
            throws DataAccessException {
        execute(new JdoCallback() {
            public Object doInJdo(PersistenceManager pm) throws JDOException {
                pm.deletePersistent(entity);
                return null;
            }
        }, true);
    }

    public void deletePersistentAll(final Collection entities)
            throws DataAccessException {
        execute(new JdoCallback() {
            public Object doInJdo(PersistenceManager pm) throws JDOException {
                pm.deletePersistentAll(entities);
                return null;
            }
        }, true);
    }

    public <T> T detachCopy(final T entity) {
        execute(new JdoCallback() {
            public T doInJdo(PersistenceManager pm) throws JDOException {
                return pm.detachCopy(entity);
            }
        }, true);
    }

    public <T> Collection<T> detachCopyAll(final Collection<T> entities)
  {
    (Collection)execute(new JdoCallback()
    {
      public Collection<T> doInJdo(PersistenceManager pm)
        throws JDOException
      {
        return pm.detachCopyAll(entities);
      }
    }, true);
  }

    public void flush() throws DataAccessException {
        execute(new JdoCallback() {
            public Object doInJdo(PersistenceManager pm) throws JDOException {
                pm.flush();
                return null;
            }
        }, true);
    }

    public <T> Collection<T> find(Class<T> entityClass)
            throws DataAccessException {
        return find(entityClass, null, null);
    }

    public <T> Collection<T> find(Class<T> entityClass, String filter)
            throws DataAccessException {
        return find(entityClass, filter, null);
    }

    public <T> Collection<T> find(final Class<T> entityClass, final String filter, final String ordering)
    throws DataAccessException
  {
    (Collection)execute(new JdoCallback()
    {
      public Collection<T> doInJdo(PersistenceManager pm)
        throws JDOException
      {
        Query query = filter != null ? pm.newQuery(entityClass, filter) : pm.newQuery(entityClass);
        JdoTemplate.this.prepareQuery(query);
        if (ordering != null) {
          query.setOrdering(ordering);
        }
        return (Collection)query.execute();
      }
    }, true);
  }

    public <T> Collection<T> find(Class<T> entityClass, String filter,
            String parameters, Object... values) throws DataAccessException {
        return find(entityClass, filter, parameters, values, null);
    }

    public <T> Collection<T> find(final Class<T> entityClass, final String filter, final String parameters, final Object[] values, final String ordering)
    throws DataAccessException
  {
    (Collection)execute(new JdoCallback()
    {
      public Collection<T> doInJdo(PersistenceManager pm)
        throws JDOException
      {
        Query query = pm.newQuery(entityClass, filter);
        JdoTemplate.this.prepareQuery(query);
        query.declareParameters(parameters);
        if (ordering != null) {
          query.setOrdering(ordering);
        }
        return (Collection)query.executeWithArray(values);
      }
    }, true);
  }

    public <T> Collection<T> find(Class<T> entityClass, String filter,
            String parameters, Map<String, ?> values)
            throws DataAccessException {
        return find(entityClass, filter, parameters, values, null);
    }

    public <T> Collection<T> find(final Class<T> entityClass, final String filter, final String parameters, final Map<String, ?> values, final String ordering)
    throws DataAccessException
  {
    (Collection)execute(new JdoCallback()
    {
      public Collection<T> doInJdo(PersistenceManager pm)
        throws JDOException
      {
        Query query = pm.newQuery(entityClass, filter);
        JdoTemplate.this.prepareQuery(query);
        query.declareParameters(parameters);
        if (ordering != null) {
          query.setOrdering(ordering);
        }
        return (Collection)query.executeWithMap(values);
      }
    }, true);
  }

    public Collection find(final String language, final Object queryObject)
    throws DataAccessException
  {
    (Collection)execute(new JdoCallback()
    {
      public Collection doInJdo(PersistenceManager pm)
        throws JDOException
      {
        Query query = pm.newQuery(language, queryObject);
        JdoTemplate.this.prepareQuery(query);
        return (Collection)query.execute();
      }
    }, true);
  }

    public Collection find(final String queryString)
    throws DataAccessException
  {
    (Collection)execute(new JdoCallback()
    {
      public Collection doInJdo(PersistenceManager pm)
        throws JDOException
      {
        Query query = pm.newQuery(queryString);
        JdoTemplate.this.prepareQuery(query);
        return (Collection)query.execute();
      }
    }, true);
  }

    public Collection find(final String queryString, final Object... values)
    throws DataAccessException
  {
    (Collection)execute(new JdoCallback()
    {
      public Collection doInJdo(PersistenceManager pm)
        throws JDOException
      {
        Query query = pm.newQuery(queryString);
        JdoTemplate.this.prepareQuery(query);
        return (Collection)query.executeWithArray(values);
      }
    }, true);
  }

    public Collection find(final String queryString, final Map<String, ?> values)
    throws DataAccessException
  {
    (Collection)execute(new JdoCallback()
    {
      public Collection doInJdo(PersistenceManager pm)
        throws JDOException
      {
        Query query = pm.newQuery(queryString);
        JdoTemplate.this.prepareQuery(query);
        return (Collection)query.executeWithMap(values);
      }
    }, true);
  }

    public <T> Collection<T> findByNamedQuery(final Class<T> entityClass, final String queryName)
    throws DataAccessException
  {
    (Collection)execute(new JdoCallback()
    {
      public Collection<T> doInJdo(PersistenceManager pm)
        throws JDOException
      {
        Query query = pm.newNamedQuery(entityClass, queryName);
        JdoTemplate.this.prepareQuery(query);
        return (Collection)query.execute();
      }
    }, true);
  }

    public <T> Collection<T> findByNamedQuery(final Class<T> entityClass, final String queryName, final Object... values)
    throws DataAccessException
  {
    (Collection)execute(new JdoCallback()
    {
      public Collection<T> doInJdo(PersistenceManager pm)
        throws JDOException
      {
        Query query = pm.newNamedQuery(entityClass, queryName);
        JdoTemplate.this.prepareQuery(query);
        return (Collection)query.executeWithArray(values);
      }
    }, true);
  }

    public <T> Collection<T> findByNamedQuery(final Class<T> entityClass, final String queryName, final Map<String, ?> values)
    throws DataAccessException
  {
    (Collection)execute(new JdoCallback()
    {
      public Collection<T> doInJdo(PersistenceManager pm)
        throws JDOException
      {
        Query query = pm.newNamedQuery(entityClass, queryName);
        JdoTemplate.this.prepareQuery(query);
        return (Collection)query.executeWithMap(values);
      }
    }, true);
  }

    public void prepareQuery(Query query) throws JDOException {
        PersistenceManagerFactoryUtils.applyTransactionTimeout(query,
                getPersistenceManagerFactory(), getJdoDialect());
    }

    private class CloseSuppressingInvocationHandler implements
            InvocationHandler {
        private final PersistenceManager target;

        public CloseSuppressingInvocationHandler(PersistenceManager target) {
            this.target = target;
        }

        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            if (method.getName().equals("equals")) {
                return Boolean.valueOf(proxy == args[0]);
            }
            if (method.getName().equals("hashCode")) {
                return Integer.valueOf(System.identityHashCode(proxy));
            }
            if (method.getName().equals("close")) {
                return null;
            }
            try {
                Object retVal = method.invoke(this.target, args);
                if ((retVal instanceof Query)) {
                    JdoTemplate.this.prepareQuery((Query) retVal);
                }
                return retVal;
            } catch (InvocationTargetException ex) {
                throw ex.getTargetException();
            }
        }
    }
}

SqlMapClientTemplate

package org.springframework.orm.ibatis;

import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapExecutor;
import com.ibatis.sqlmap.client.event.RowHandler;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.JdbcUpdateAffectedIncorrectNumberOfRowsException;
import org.springframework.jdbc.support.JdbcAccessor;

@Deprecated
public class SqlMapClientTemplate extends JdbcAccessor implements
        SqlMapClientOperations {
    private SqlMapClient sqlMapClient;

    public SqlMapClientTemplate() {
    }

    public SqlMapClientTemplate(SqlMapClient sqlMapClient) {
        setSqlMapClient(sqlMapClient);
        afterPropertiesSet();
    }

    public SqlMapClientTemplate(DataSource dataSource, SqlMapClient sqlMapClient) {
        setDataSource(dataSource);
        setSqlMapClient(sqlMapClient);
        afterPropertiesSet();
    }

    public void setSqlMapClient(SqlMapClient sqlMapClient) {
        this.sqlMapClient = sqlMapClient;
    }

    public SqlMapClient getSqlMapClient() {
        return this.sqlMapClient;
    }

    public DataSource getDataSource() {
        DataSource ds = super.getDataSource();
        return ds != null ? ds : this.sqlMapClient.getDataSource();
    }

    public void afterPropertiesSet() {
        if (this.sqlMapClient == null) {
            throw new IllegalArgumentException(
                    "Property 'sqlMapClient' is required");
        }
        super.afterPropertiesSet();
    }

    /* Error */
    public <T> T execute(SqlMapClientCallback<T> action)
            throws DataAccessException {

    }

    @Deprecated
    public List executeWithListResult(SqlMapClientCallback<List> action)
            throws DataAccessException {
        return (List) execute(action);
    }

    @Deprecated
    public Map executeWithMapResult(SqlMapClientCallback<Map> action)
            throws DataAccessException {
        return (Map) execute(action);
    }

    public Object queryForObject(String statementName)
            throws DataAccessException {
        return queryForObject(statementName, null);
    }

    public Object queryForObject(final String statementName,
            final Object parameterObject) throws DataAccessException {
        execute(new SqlMapClientCallback() {
            public Object doInSqlMapClient(SqlMapExecutor executor)
                    throws SQLException {
                return executor.queryForObject(statementName, parameterObject);
            }
        });
    }

    public Object queryForObject(final String statementName,
            final Object parameterObject, final Object resultObject)
            throws DataAccessException {
        execute(new SqlMapClientCallback() {
            public Object doInSqlMapClient(SqlMapExecutor executor)
                    throws SQLException {
                return executor.queryForObject(statementName, parameterObject,
                        resultObject);
            }
        });
    }

    public List queryForList(String statementName) throws DataAccessException {
        return queryForList(statementName, null);
    }

    public List queryForList(final String statementName, final Object parameterObject)
    throws DataAccessException
  {
    (List)execute(new SqlMapClientCallback()
    {
      public List doInSqlMapClient(SqlMapExecutor executor)
        throws SQLException
      {
        return executor.queryForList(statementName, parameterObject);
      }
    });
  }

    public List queryForList(String statementName, int skipResults,
            int maxResults) throws DataAccessException {
        return queryForList(statementName, null, skipResults, maxResults);
    }

    public List queryForList(final String statementName, final Object parameterObject, final int skipResults, final int maxResults)
    throws DataAccessException
  {
    (List)execute(new SqlMapClientCallback()
    {
      public List doInSqlMapClient(SqlMapExecutor executor)
        throws SQLException
      {
        return executor.queryForList(statementName, parameterObject, skipResults, maxResults);
      }
    });
  }

    public void queryWithRowHandler(String statementName, RowHandler rowHandler)
            throws DataAccessException {
        queryWithRowHandler(statementName, null, rowHandler);
    }

    public void queryWithRowHandler(final String statementName,
            final Object parameterObject, final RowHandler rowHandler)
            throws DataAccessException {
        execute(new SqlMapClientCallback() {
            public Object doInSqlMapClient(SqlMapExecutor executor)
                    throws SQLException {
                executor.queryWithRowHandler(statementName, parameterObject,
                        rowHandler);
                return null;
            }
        });
    }

    public Map queryForMap(final String statementName, final Object parameterObject, final String keyProperty)
    throws DataAccessException
  {
    (Map)execute(new SqlMapClientCallback()
    {
      public Map doInSqlMapClient(SqlMapExecutor executor)
        throws SQLException
      {
        return executor.queryForMap(statementName, parameterObject, keyProperty);
      }
    });
  }

    public Map queryForMap(final String statementName, final Object parameterObject, final String keyProperty, final String valueProperty)
    throws DataAccessException
  {
    (Map)execute(new SqlMapClientCallback()
    {
      public Map doInSqlMapClient(SqlMapExecutor executor)
        throws SQLException
      {
        return executor.queryForMap(statementName, parameterObject, keyProperty, valueProperty);
      }
    });
  }

    public Object insert(String statementName) throws DataAccessException {
        return insert(statementName, null);
    }

    public Object insert(final String statementName,
            final Object parameterObject) throws DataAccessException {
        execute(new SqlMapClientCallback() {
            public Object doInSqlMapClient(SqlMapExecutor executor)
                    throws SQLException {
                return executor.insert(statementName, parameterObject);
            }
        });
    }

    public int update(String statementName) throws DataAccessException {
        return update(statementName, null);
    }

    public int update(final String statementName, final Object parameterObject)
            throws DataAccessException {
        ((Integer) execute(new SqlMapClientCallback() {
            public Integer doInSqlMapClient(SqlMapExecutor executor)
                    throws SQLException {
                return Integer.valueOf(executor.update(statementName,
                        parameterObject));
            }
        })).intValue();
    }

    public void update(String statementName, Object parameterObject,
            int requiredRowsAffected) throws DataAccessException {
        int actualRowsAffected = update(statementName, parameterObject);
        if (actualRowsAffected != requiredRowsAffected) {
            throw new JdbcUpdateAffectedIncorrectNumberOfRowsException(
                    statementName, requiredRowsAffected, actualRowsAffected);
        }
    }

    public int delete(String statementName) throws DataAccessException {
        return delete(statementName, null);
    }

    public int delete(final String statementName, final Object parameterObject)
            throws DataAccessException {
        ((Integer) execute(new SqlMapClientCallback() {
            public Integer doInSqlMapClient(SqlMapExecutor executor)
                    throws SQLException {
                return Integer.valueOf(executor.delete(statementName,
                        parameterObject));
            }
        })).intValue();
    }

    public void delete(String statementName, Object parameterObject,
            int requiredRowsAffected) throws DataAccessException {
        int actualRowsAffected = delete(statementName, parameterObject);
        if (actualRowsAffected != requiredRowsAffected) {
            throw new JdbcUpdateAffectedIncorrectNumberOfRowsException(
                    statementName, requiredRowsAffected, actualRowsAffected);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值