基于Mybatis原理实现的自定义持久框架

本次演示主基于mybatis原理实现,用Java+jdbc进行封装的一个持久类框架;


pom.xml


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>ipersistent</groupId>
    <artifactId>Ipersistence</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.release>1.8</maven.compiler.release>
    </properties>
    <dependencies>
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-core</artifactId>
            <version>2.3.0</version>
        </dependency>

        <dependency>

            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.17</version>
        </dependency>
        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.1.2</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
        </dependency>
        <dependency>
            <groupId>dom4j</groupId>
            <artifactId>dom4j</artifactId>
            <version>1.6.1</version>
        </dependency>
        <dependency>
            <groupId>jaxen</groupId>
            <artifactId>jaxen</artifactId>
            <version>1.1.6</version>
        </dependency>
    </dependencies>

    <build>
        <pluginManagement>
            <plugins>
                <!--This plugin's configuration is used to store Eclipse m2e settings 
                    only. It has no influence on the Maven build itself. -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-toolchains-plugin</artifactId>
                    <configuration>
                        <toolchains>
                            <jdk>
                                <version>1.8</version>
                                <vendor>mysql</vendor>
                            </jdk>
                        </toolchains>
                    </configuration>
                    <executions>
                        <execution>
                            <goals>
                                <goal>toolchain</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>

            </plugins>
        </pluginManagement>
    </build>
</project>


SqpMapConfig.xml(相当于mybatis.xml)

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
    <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
    <property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/lin_xu_db"></property>
    <property name="user" value="root"></property>
    <property name="password" value="root"></property>
    <mapper resource="UserMapper.xml"></mapper>
</configuration>


UserMapper.xml(相当于mybatis的mapper)

<?xml version="1.0" encoding="UTF-8"?>

<mapper namespace="com.test.UserDao">
    <select id="selectUser" paramterType="com.test.User" resultType="com.test.User" autocommit="false">
        select * from user_tb
    </select>
</mapper>


配置解析


import java.util.HashMap;
import java.util.Map;

import javax.sql.DataSource;
/**
 * 
 * @author linxu
 *
 */
public class Configuration {
    private DataSource dataSource;

    private Map<String, MappedStatement> mappedStatement = new HashMap<String, MappedStatement>();

    public DataSource getDataSource() {
        return dataSource;
    }

    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public Map<String, MappedStatement> getMappedStatement() {
        return mappedStatement;
    }

    public void setMappedStatement(Map<String, MappedStatement> mappedStatement) {
        this.mappedStatement = mappedStatement;
    }

}




package com.Ipersistence.configuration;
/**
 * 
 * @author linxu
 *
 */
public class MappedStatement {
    private String id;// id标识
    private Class<?> resultType;// 返回值类型
    private Class<?> paramterType;// 参数类型
    private String sql;// SQL
    private String dbAction;// updata/insert/select/delete标识
    private boolean autoCommit;//

    public MappedStatement(Builder builder) {
        this.id = builder.id;
        this.resultType = builder.resultType;
        this.paramterType = builder.paramterType;
        this.sql = builder.sql;
        this.dbAction = builder.dbAction;
        this.autoCommit=builder.autoCommit;
    }

    public boolean isAutoCommit() {
        return autoCommit;
    }

    public void setAutoCommit(boolean autoCommit) {
        this.autoCommit = autoCommit;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }


    public Class<?> getResultType() {
        return resultType;
    }

    public void setResultType(Class<?> resultType) {
        this.resultType = resultType;
    }

    public Class<?> getParamterType() {
        return paramterType;
    }

    public void setParamterType(Class<?> paramterType) {
        this.paramterType = paramterType;
    }

    public String getSql() {
        return sql;
    }

    public void setSql(String sql) {
        this.sql = sql;
    }

    public String getDbAction() {
        return dbAction;
    }

    public void setDbAction(String dbAction) {
        this.dbAction = dbAction;
    }

    public static class Builder {
        private String id;// id标识
        private Class<?> resultType;// 返回值类型
        private Class<?> paramterType;// 参数类型
        private String sql;// SQL
        private String dbAction;
        private boolean autoCommit;//

        public Builder putId(String id) {
            this.id = id;
            return this;
        }

        public Builder putResultType(Class<?> resultType) {
            this.resultType = resultType;
            return this;
        }

        public Builder putParamterType(Class<?> paramterType) {

            this.paramterType = paramterType;
            return this;

        }

        public Builder putSql(String sql) {
            this.sql = sql;
            return this;
        }

        public Builder putDbAction(String dbAction) {
            this.dbAction = dbAction;
            return this;

        }

        public MappedStatement builder() {
            return new MappedStatement(this);
        }

        public Builder putAutoCommit(boolean autoCommit) {
            this.autoCommit=autoCommit;
            return this;
            
        }
    }

}



package com.Ipersistence.configuration;

import java.beans.PropertyVetoException;
import java.io.InputStream;
import java.util.List;
import java.util.Properties;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.Ipersistence.io.Resources;
import com.mchange.v2.c3p0.ComboPooledDataSource;
/**
 * 
 * @author linxu
 *
 */
public class XMLConfigerBuilder {
    private Configuration configuration;

    public XMLConfigerBuilder() {
        this.configuration = new Configuration();
    }

    public Configuration getConfiguration() {
        return configuration;
    }

    public void setConfiguration(Configuration configuration) {
        this.configuration = configuration;
    }

    @SuppressWarnings("unchecked")
    public Configuration parseConfig(InputStream inputStream) throws DocumentException, PropertyVetoException {
        Document document = new SAXReader().read(inputStream);
        Element rootElement = document.getRootElement();
        List<Element> configElement = rootElement.selectNodes("property");
        Properties properties = new Properties();
        for (Element element : configElement) {
            String nameproperty = element.attributeValue("name");
            String valueProperty = element.attributeValue("value");
            properties.setProperty(nameproperty, valueProperty);
        }
        ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
        comboPooledDataSource.setUser(properties.getProperty("user"));
        comboPooledDataSource.setJdbcUrl(properties.getProperty("jdbcUrl"));
        comboPooledDataSource.setPassword(properties.getProperty("password"));
        comboPooledDataSource.setDriverClass(properties.getProperty("driverClass"));
        configuration.setDataSource(comboPooledDataSource);

        // 解析mapper.xml文件
        List<Element> mapperElement = rootElement.selectNodes("//mapper");
        XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(configuration);
        for (Element element : mapperElement) {
            String mapperResource = element.attributeValue("resource");
            InputStream mapperInputStream = Resources.getResourceAsStream(mapperResource);
            xmlMapperBuilder.parseMapper(mapperInputStream);
        }
        return configuration;

    }

}




package com.Ipersistence.configuration;

import java.io.InputStream;
import java.util.List;

import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

/**
 * 
 * @author linxu
 *
 */
public class XMLMapperBuilder {
    Configuration configuration;

    public XMLMapperBuilder(Configuration configuration) {
        this.configuration = configuration;
    }

    public void parseMapper(InputStream inputStream) throws DocumentException {
        parseXml(new SAXReader().read(inputStream).getRootElement(), "select", "insert", "delete", "update");
    }

    @SuppressWarnings("unchecked")
    public void parseXml(Element rootElement, String... dbActions) {
        String namespace = rootElement.attributeValue("namespace");
        for (int i = 0; i < dbActions.length; i++) {
            List<Element> elements = rootElement.selectNodes(dbActions[i]);
            if (elements != null && !elements.isEmpty()) {
                for (Element element : elements) {
                    String id = element.attributeValue("id");
                    String paramterType = element.attributeValue("paramterType");
                    String resultType = element.attributeValue("resultType");
                    String sqlText = element.getTextTrim();
                    String autoVommit = element.attributeValue("autocommit").trim();
                    configuration.getMappedStatement().put(namespace + "." + id,
                            new MappedStatement.Builder().putId(id).putParamterType(getClassType(paramterType))
                                    .putResultType(getClassType(resultType)).putSql(sqlText).putDbAction(dbActions[i])
                                    .putAutoCommit(autoVommit.isEmpty() ? true : autoVommit.equals("true")).builder());
                }
            }
        }
    }

    private Class<?> getClassType(String className) {
        if (!className.isEmpty()) {
            try {
                return Class.forName(className);
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        return null;

    }

}



Session工厂(实现类似mybatis的session访问,利用动态代理实现类似mybatis的接口式开发)


package com.Ipersistence.session;

import java.sql.SQLException;
import java.util.List;
/**
 * 
 * @author linxu
 *
 */
public interface SqlSession {
    public <E> List<E> selectList(String statementId, Object... params)throws SecurityException, SQLException, Exception;

    public <E> E selectOne(String statementId, Object... params) throws SecurityException, SQLException, Exception;

    public int executeUpdate(String statementId, Object... params) throws SecurityException, SQLException, Exception;

    public int update(String statementId, Object... params) throws SecurityException, SQLException, Exception;

    public int insert(String statementId, Object... params) throws SecurityException, SQLException, Exception;

    public int delete(String statementId, Object... params) throws SecurityException, SQLException, Exception;

    public void close();

    public <T> T getMapper(Class<?> mapperClass);

    public void commit();
}




package com.Ipersistence.session;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Proxy;
import java.sql.SQLException;
import java.util.List;

import com.Ipersistence.configuration.Configuration;
import com.Ipersistence.configuration.MappedStatement;
import com.Ipersistence.executor.BaseExecutor;
import com.Ipersistence.executor.Executor;

/**
 * 
 * @author ;linxu
 *
 */
public class DefaultSession implements SqlSession {
    private Configuration configuration;

    public DefaultSession(Configuration configuration) {
        this.configuration = configuration;
    }

    Executor baseExecutor = new BaseExecutor();

    @Override
    public <E> List<E> selectList(String statementId, Object... params)
            throws SecurityException, SQLException, Exception {
        final MappedStatement mappedStatement = configuration.getMappedStatement().get(statementId);
        if (mappedStatement != null) {
            return baseExecutor.query(configuration, mappedStatement, params);
        }
        return null;
    }

    @Override
    public <E> E selectOne(String statementId, Object... params) throws SecurityException, SQLException, Exception {
        List<E> list = selectList(statementId, params);
        if (list != null && list.size() == 1) {
            return list.get(0);
        } else {
            throw new RuntimeException("查询数据为Null或则查询数据过多:");
        }
    }

    @Override
    public int executeUpdate(String statementId, Object... params) throws SecurityException, SQLException, Exception {
        final MappedStatement mappedStatement = configuration.getMappedStatement().get(statementId);
        if (mappedStatement == null) {
            return this.baseExecutor.executeUpdate(configuration, mappedStatement, params);
        }
        return 0;
    }

    @Override
    public int update(String statementId, Object... params) throws SecurityException, SQLException, Exception {
        // TODO Auto-generated method stub
        return this.executeUpdate(statementId, params);
    }

    @Override
    public int insert(String statementId, Object... params) throws SecurityException, SQLException, Exception {
        // TODO Auto-generated method stub
        return this.executeUpdate(statementId, params);
    }

    @Override
    public int delete(String statementId, Object... params) throws SecurityException, SQLException, Exception {
        // TODO Auto-generated method stub
        return this.executeUpdate(statementId, params);
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T> T getMapper(Class<?> mapperClass) {
        Object proxy = Proxy.newProxyInstance(DefaultSession.class.getClassLoader(), new Class[] { mapperClass },
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] params) throws Throwable {
                        // 方法名字
                        String methodname = method.getName();
                        // 获取接口类
                        String className = method.getDeclaringClass().getName();
                        String statementId = className + "." + methodname;
                        java.lang.reflect.Type resultType = method.getGenericReturnType();
                        MappedStatement mappedStatement = configuration.getMappedStatement().get(statementId);
                        if (mappedStatement == null) {
                            throw new RuntimeException("sql配置不存在:" + DefaultSession.class.getName());
                        }
                        if (mappedStatement.getDbAction().equals("select")) {
                            // 如果返回值类型是泛型,调用selectList,否则selectOne
                            if (resultType instanceof ParameterizedType) {
                                return selectList(statementId, params);
                            } else {
                                return selectOne(statementId, params);
                            }
                        } else if (mappedStatement.getDbAction().equals("insert")
                                || mappedStatement.getDbAction().equals("delete")
                                || mappedStatement.getDbAction().equals("update")) {
                            return executeUpdate(statementId, params);
                        } else {
                            throw new RuntimeException("mapper配置文件错误:");
                        }
                    }
                });
        return (T) proxy;
    }

    @Override
    public void close() {
        try {
            baseExecutor.close();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    @Override
    public void commit() {
        try {
            baseExecutor.commit();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

}



package com.Ipersistence.session;

/**
 * SqlSessionFactory工厂类:生产SqlSession
 * @author linxu
 *
 */
public interface SqlSessionFactory{
    public SqlSession openSession();
}



package com.Ipersistence.session;

import com.Ipersistence.configuration.Configuration;
/**
 * 
 * @author linxu
 *
 */
public class DefaultSqlSessionFactory implements SqlSessionFactory {
    private Configuration configuration;


    public DefaultSqlSessionFactory(Configuration configuration) {
        this.configuration = configuration;
    }

    @Override
    public SqlSession openSession() {
        // TODO Auto-generated method stub
        return new DefaultSession(configuration);
    }

}




package com.Ipersistence.session;

import java.beans.PropertyVetoException;
import java.io.InputStream;

import org.dom4j.DocumentException;

import com.Ipersistence.configuration.Configuration;
import com.Ipersistence.configuration.XMLConfigerBuilder;

/**
 * SqlSessionFactoryBuilder,利用配置构建个SqlSessionFactory工厂
 * 
 * @author linxu
 * 
 */
public class SqlSessionFactoryBuilder {
    private Configuration configuration;

    /**
     * 
     * @param inputStream
     * @return
     * @throws PropertyVetoException
     * @throws DocumentException
     */
    public SqlSessionFactory builder(InputStream inputStream) throws DocumentException, PropertyVetoException {
        XMLConfigerBuilder xMLConfigerBuilder = new XMLConfigerBuilder();
        this.configuration = xMLConfigerBuilder.parseConfig(inputStream);
        DefaultSqlSessionFactory defaultSqlSessionFactory = new DefaultSqlSessionFactory(configuration);
        return defaultSqlSessionFactory;
    }
}


Io读取

package com.Ipersistence.io;

import java.io.InputStream;
/**
 * 
 * @author linxu
 *
 */
public class Resources {
     /**
      * 
      * @param path
      * @return
      */
    public static InputStream getResourceAsStream(String path) {
        return Resources.class.getClassLoader().getResourceAsStream(path);
    }
}



Executor实现(主要封装了jdbc对数据库的操作)

package com.Ipersistence.executor;

import java.sql.SQLException;
import java.util.List;

import com.Ipersistence.boundsql.BoundSql;
import com.Ipersistence.configuration.Configuration;
import com.Ipersistence.configuration.MappedStatement;
/**
 * 
 * @author linxu
 *
 */
public interface Executor {
    public <E> List<E> query(Configuration configuration, MappedStatement mappedStatement, Object... params)
            throws SQLException, Exception, SecurityException;

    public int executeUpdate(Configuration configuration, MappedStatement mappedStatement, Object... params)
            throws SQLException, Exception, SecurityException;

    // 关闭连接操作
    public void close() throws SQLException;

    public BoundSql getBoundSql(String sql);
    
    public void commit() throws SQLException;

}



package com.Ipersistence.executor;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.Ipersistence.boundsql.BoundSql;
import com.Ipersistence.configuration.Configuration;
import com.Ipersistence.configuration.MappedStatement;
import com.Ipersistence.utils.GenericTokenParser;
import com.Ipersistence.utils.ParameterMapping;
import com.Ipersistence.utils.ParameterMappingTokenHandler;
/**
 * 
 * @author linxu
 *
 */
public class BaseExecutor implements Executor {
    private Connection connection;

    @SuppressWarnings("unchecked")
    @Override
    public <E> List<E> query(Configuration configuration, MappedStatement mappedStatement, Object... params)
            throws SQLException, Exception, SecurityException {
        this.connection = configuration.getDataSource().getConnection();
        String sql = mappedStatement.getSql();
        BoundSql boundSql = getBoundSql(sql);
        PreparedStatement preparedStatement = connection.prepareStatement(boundSql.getSqlText());
        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
        if(parameterMappings!=null&&!parameterMappings.isEmpty()) {
        for (int i = 0; i < parameterMappings.size(); i++) {
            ParameterMapping parameterMapping = parameterMappings.get(i);
            String valuename = parameterMapping.getContent();
            // 鎷垮埌杩欎釜瀛楁瀵硅薄
            Field field = mappedStatement.getParamterType().getDeclaredField(valuename);
            // 璁剧疆鏉冮檺
            field.setAccessible(true);
            Object o = field.get(params[0]);
            preparedStatement.setObject(i + 1, o);
        }
        }
        // 鎵ц鏁版嵁鏌ヨ
        ResultSet resultSet = preparedStatement.executeQuery();
        // 瑙f瀽鏁版嵁
        List<E> result_list = new ArrayList<>();
        while (resultSet.next()) {
            ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
            E e = (E) mappedStatement.getResultType().newInstance();
            for (int i = 1; i <= resultSetMetaData.getColumnCount(); i++) {
                String columnname = resultSetMetaData.getColumnName(i);
                Object value = resultSet.getObject(columnname);
                PropertyDescriptor propertyDescriptor = new PropertyDescriptor(columnname,
                        mappedStatement.getResultType());
                Method method = propertyDescriptor.getWriteMethod();
                method.invoke(e, value);
            }
            result_list.add(e);
        }
        return result_list;
    }

    @Override
    public int executeUpdate(Configuration configuration, MappedStatement mappedStatement, Object... params)
            throws SQLException, Exception, SecurityException {
        // 瀹屾垚瀵规暟鎹簱鑳¤闂�
        // 1鑾峰彇杩炴帴
        connection = configuration.getDataSource().getConnection();
        // 鍒ゆ柇鏄惁鏄缃嚜鍔ㄦ彁浜�
        if (mappedStatement.isAutoCommit())
            connection.setAutoCommit(true);
        // 鍏抽棴鑷姩鎻愪氦
        connection.setAutoCommit(false);
        // 2鑾峰彇Sql
        String sql = mappedStatement.getSql();
        // 3杞崲sql,灏嗚В鏋�
        BoundSql boundSql = getBoundSql(sql);
        // 4鑾峰彇棰勫鐞嗗璞reparedStatement
        PreparedStatement preparedStatement = connection.prepareStatement(boundSql.getSqlText());
        // 鑾峰彇鍙傛暟瀵硅薄绫诲瀷
        Class<?> parameterClass = mappedStatement.getParamterType();
        // 鏁版嵁鍙傛暟璁剧疆
        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
        for (int i = 0; i < parameterMappings.size(); i++) {
            ParameterMapping parameterMapping = parameterMappings.get(i);
            String content = parameterMapping.getContent();
            // 鑾峰彇灞炴�у璞�
            Field field = parameterClass.getDeclaredField(content);
            // 璁剧疆鏉冮檺
            field.setAccessible(true);
            // 鑾峰彇灞炴�у璞″��
            Object o = field.get(params[0]);
            // 瑷疆鍙傛暟
            preparedStatement.setObject(i + 1, o);
        }

        // 鎵цsql
        return preparedStatement.executeUpdate();
    }

    @Override
    public void close() throws SQLException {
        if (connection != null) {
            this.connection.close();
        }

    }

    @Override
    public BoundSql getBoundSql(String sql) {
        final ParameterMappingTokenHandler parameterMappingTokenHandler = new ParameterMappingTokenHandler();
        final GenericTokenParser genericTokenParser = new GenericTokenParser("#{", "}", parameterMappingTokenHandler);
        String sqlText = genericTokenParser.parse(sql);
        List<ParameterMapping> parameterMappings = parameterMappingTokenHandler.getParameterMappings();
        return new BoundSql.Builder().putSqlText(sqlText).putParameterMappings(parameterMappings).builder();
    }

    @Override
    public void commit() throws SQLException {
        // 濡傛灉宸茬粡璁剧疆涓鸿嚜鍔ㄦ彁浜や簡锛屽氨娌″繀瑕佸啀閲嶅鎻愪氦
        if (connection != null) {
            if (connection.getAutoCommit() == true) {
                return;
            }
            try {
                connection.commit();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

}


sql转换(和mybatis原理一致)

package com.Ipersistence.boundsql;

import java.util.List;

import com.Ipersistence.utils.ParameterMapping;

/**
 * 转换sql
 * @author linxu
 *
 */
public class BoundSql {
    private String sqlText;
    private List<ParameterMapping> parameterMappings;

    public String getSqlText() {
        return sqlText;
    }

    public void setSqlText(String sqlText) {
        this.sqlText = sqlText;
    }

    public List<ParameterMapping> getParameterMappings() {
        return parameterMappings;
    }

    public void setParameterMappings(List<ParameterMapping> parameterMappings) {
        this.parameterMappings = parameterMappings;
    }

    public BoundSql(Builder builder) {
        this.sqlText = builder.sqlText;
        this.parameterMappings = builder.parameterMappings;
    }

    public static class Builder {
        private String sqlText;
        private List<ParameterMapping> parameterMappings;

        public Builder putSqlText(String sql) {
            this.sqlText = sql;
            return this;
        }

        public Builder putParameterMappings(List<ParameterMapping> parameterMappings) {
            this.parameterMappings = parameterMappings;
            return this;
        }

        public BoundSql builder() {
            return new BoundSql(this);
        }

    }

}


以下工具类是我从mybatis拷贝而来的,也贴上

/**
 *    Copyright 2009-2017 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package com.Ipersistence.utils;

/**
 * @author Clinton Begin
 */
public class GenericTokenParser {

  private final String openToken; //�?始标�?
  private final String closeToken; //结束标记
  private final TokenHandler handler; //标记处理�?

  public GenericTokenParser(String openToken, String closeToken, TokenHandler handler) {
    this.openToken = openToken;
    this.closeToken = closeToken;
    this.handler = handler;
  }

  /**
   * 解析${}�?#{}
   * @param text
   * @return
   * 该方法主要实现了配置文件、脚本等片段中占位符的解析�?�处理工作,并返回最终需要的数据�?
   * 其中,解析工作由该方法完成,处理工作是由处理器handler的handleToken()方法来实�?
   */
  public String parse(String text) {
    // 验证参数问题,如果是null,就返回空字符串�?
    if (text == null || text.isEmpty()) {
      return "";
    }

    // 下面继续验证是否包含�?始标签,如果不包含,默认不是占位符,直接原样返回即可,否则继续执行�??
    int start = text.indexOf(openToken, 0);
    if (start == -1) {
      return text;
    }

   // 把text转成字符数组src,并且定义默认偏移量offset=0、存储最终需要返回字符串的变量builder�?
    // text变量中占位符对应的变量名expression。判断start是否大于-1(即text中是否存在openToken),如果存在就执行下面代码
    char[] src = text.toCharArray();
    int offset = 0;
    final StringBuilder builder = new StringBuilder();
    StringBuilder expression = null;
    while (start > -1) {
     // 判断如果�?始标记前如果有转义字符,就不作为openToken进行处理,否则继续处�?
      if (start > 0 && src[start - 1] == '\\') {
        builder.append(src, offset, start - offset - 1).append(openToken);
        offset = start + openToken.length();
      } else {
        //重置expression变量,避免空指针或�?��?�数据干扰�??
        if (expression == null) {
          expression = new StringBuilder();
        } else {
          expression.setLength(0);
        }
        builder.append(src, offset, start - offset);
        offset = start + openToken.length();
        int end = text.indexOf(closeToken, offset);
        while (end > -1) {////存在结束标记�?
          if (end > offset && src[end - 1] == '\\') {//如果结束标记前面有转义字符时
            // this close token is escaped. remove the backslash and continue.
            expression.append(src, offset, end - offset - 1).append(closeToken);
            offset = end + closeToken.length();
            end = text.indexOf(closeToken, offset);
          } else {//不存在转义字符,即需要作为参数进行处�?
            expression.append(src, offset, end - offset);
            offset = end + closeToken.length();
            break;
          }
        }
        if (end == -1) {
          // close token was not found.
          builder.append(src, start, src.length - start);
          offset = src.length;
        } else {
          //首先根据参数的key(即expression)进行参数处理,返回?作为占位�?
          builder.append(handler.handleToken(expression.toString()));
          offset = end + closeToken.length();
        }
      }
      start = text.indexOf(openToken, offset);
    }
    if (offset < src.length) {
      builder.append(src, offset, src.length - offset);
    }
    return builder.toString();
  }
}



package com.Ipersistence.utils;

public class ParameterMapping {

    private String content;

    public ParameterMapping(String content) {
        this.content = content;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }
}


package com.Ipersistence.utils;

import java.util.ArrayList;
import java.util.List;




public class ParameterMappingTokenHandler implements TokenHandler {
    private List<ParameterMapping> parameterMappings = new ArrayList<ParameterMapping>();

    // context是参数名�? #{id} #{username}

    public String handleToken(String content) {
        parameterMappings.add(buildParameterMapping(content));
        return "?";
    }

    private ParameterMapping buildParameterMapping(String content) {
        ParameterMapping parameterMapping = new ParameterMapping(content);
        return parameterMapping;
    }

    public List<ParameterMapping> getParameterMappings() {
        return parameterMappings;
    }

    public void setParameterMappings(List<ParameterMapping> parameterMappings) {
        this.parameterMappings = parameterMappings;
    }

}



/**
 *    Copyright 2009-2015 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package com.Ipersistence.utils;

/**
 * @author Clinton Begin
 */
public interface TokenHandler {
  String handleToken(String content);
}




测试:


package com.test;

public class User {

    private int id;
    private String username;
    private String userid;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getUserid() {
        return userid;
    }
    public void setUserid(String userid) {
        this.userid = userid;
    }
    @Override
    public String toString() {
        return "User [id=" + id + ", username=" + username + ", userid=" + userid + ", getId()=" + getId()
                + ", getUsername()=" + getUsername() + ", getUserid()=" + getUserid() + ", getClass()=" + getClass()
                + ", hashCode()=" + hashCode() + ", toString()=" + super.toString() + "]";
    }
    
}


//dao接口
package com.test;

import java.util.List;

public interface UserDao {
public List<User>selectUser(User user);
}



package com.test;

import java.beans.PropertyVetoException;

import org.dom4j.DocumentException;

import com.Ipersistence.io.Resources;
import com.Ipersistence.session.SqlSession;
import com.Ipersistence.session.SqlSessionFactory;
import com.Ipersistence.session.SqlSessionFactoryBuilder;

public class UserTest {
public static void main(String[] args) throws DocumentException, PropertyVetoException {
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder()
            .builder(Resources.getResourceAsStream("SqlMapConfig.xml"));
    SqlSession sqlSession = sqlSessionFactory.openSession();
    UserDao userDao = sqlSession.getMapper(UserDao.class);
    User user=new User();
    
    
    System.err.println(userDao.selectUser(user).toString());
    sqlSession.close();
}

}

猜你喜欢

转载自www.cnblogs.com/mature1021/p/13371066.html
今日推荐