以查询为例

创建SqlSession接口

public interface SqlSession{
     <T> List<T> queryList() throws Exception;
}

创建SqlSessionImpl类,实现SqlSession接口

public class SqlSessionImpl implements SqlSession{
     public <T> List<T> queryList()  throws Exception{
          String driver="com.mysql.cj.jdbc.Driver";
          String url="jdbc:mysql://localhost:3306/testdb?characterEncoding=utf8&useSSL=false&useUnicode=true&allowPublicKeyRetrieval=false&serverTimezone=GMT";
          String username="sa";
          String password="admin";
          //加载驱动
          Class.forName(driver);
          //建立连接
          Connection connection= DriverManager.getConnection(url,username,password);
          //创建Statement
          Statement statement=connection.createStatement();
          //执行sql
          String sql="select * from userinfo";
          ResultSet resultSet=statement.executeQuery(sql);
          //处理ResultSet
          List<T> list=new ArrayList<>();
          User user;
          while(resultSet.next()){
                user=new User();
                user.setUserId(resultSet.getInt("userid"));
                user.setUserName(resultSet.getString("username"));
                user.setUserSex(resultSet.getString("usersex"));
                user.setUserAge(resultSet.getInt("userAge"));
                user.setUserAddress(resultSet.getString("useraddress"));
                list.add((T)user);
          }
          //释放资源
          if(resultSet!=null){
                resultSet.close();
          }
          if(statement!=null){
               statement.close();
          }
          if(connection!=null){
               connection.close();
          }
          return list;
     }
}

待处理的问题

  1. 数据库连接信息放置配置文件中
  2. Sql语句放置在配置文件中
  3. 结果集封装对象类型放置配置文件中
  4. 数据库中表对应的数据设置到对象中

处理数据库中表对应的数据设置到对象中

ResultSet resultSet=statement.executeQuery(sql);
//返回list
List<T> list=new ArrayList<>();
Object obj=null;
String resultType="com.company.pojo.User";
Class<?> clazz=Class.forName(resultType);
//获取ResultSet元数据
ResultSetMetaData metaData=resultSet.getMetaData();
//获取ResultSet列名
List<String> columnNameList=new ArrayList<>();
for(int i=1;i<=metaData.getColumnCount();i++){
     String columnName=metaData.getColumnName(i);
     columnNameList.add(columnName);
}
//获取类中的方法 setXXX getXXX等方法
Method[] methods=clazz.getMethods();
while(resultSet.next()){
     obj=clazz.newInstance();
     //处理将结果集中数据填充到对象中的问题
     for(String columnName:columnNameList){
          Object columnValue=result.getObject(columnName);
          //遍历类中的方法
          for(Method method:methods){
                //获取方法名
                String name=method.getName();
                if(name.equalsIgnoreCase("set"+columnName)){
                      //利用反射执行方法赋值
                      method.invoke(obj,columnValue);
                }
          }
     }
     list.add(obj);
}
return list;

处理数据库连接信息放到Configuration对象中(Mybatis 解析XML)

SqlSessionImpl.java代码中

private Configuration configuration;

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

public <T> List<T> queryList(String sqlId) throws Exception{
     String driver=configuration.getDriver();
     String url=configuration.getUrl();
     String username=configuration.getUsername();
     String password=configuration.getPassword();
     //......
} 

在解决问题2和3,先看配置文件SqlMapConfig.xml和UserMapper.xml。

SqlMapConfig.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/testdb?characterEncoding=utf8&amp;useSSL=false&amp;serverTimezone=GMT&amp;allowPublicKeyRetrieval=false&amp;useUnicode=true" />
                <property name="username" value="sa" />
                <property name="password" value="admin" />
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="UserMapper.xml" />
    </mappers>
</configuration>

UserMapper.xml

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.company.pojo.UserMapper">
    <select id="queryUserList" resultType="com.company.pojo.User">
        select * from userinfo</select>
</mapper>

定义Mapper.java类

public class Mapper {
   //sql语句
   private String sql;
   //结果集封装的对象类型
   private String resultType;

    public String getSql() {
        return sql;
    }

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

    public String getResultType() {
        return resultType;
    }

    public void setResultType(String resultType) {
        this.resultType = resultType;
    }

    @Override
    public String toString() {
        return "Mapper{" +
                "sql='" + sql + '\'' +
                ", resultType='" + resultType + '\'' +
                '}';
    }
}

将sql语句和结果集封装对象的类型的Mapper与sqlId一一对应,一起封装在Configuration对象中。

Configuration.java

public class Configuration {
    //数据库驱动
    private String driver;
    //数据库连接url
    private String url;
    //数据库连接账户
    private String username;
    //数据库账户对应密码
    private String password;
    //sqlId和对应的封装对象类型及sql语句
    private Map<String, Mapper> mapperMap=new HashMap<>();

    @Override
    public String toString() {
        return "Configuration{" +
                "driver='" + driver + '\'' +
                ", url='" + url + '\'' +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", mapperMap=" + mapperMap +
                '}';
    }

    public String getDriver() {
        return driver;
    }

    public void setDriver(String driver) {
        this.driver = driver;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Map<String, Mapper> getMapperMap() {
        return mapperMap;
    }

    public void setMapperMap(Map<String, Mapper> mapperMap) {
        this.mapperMap = mapperMap;
    }
}

解析SqlMapConfig.xml和UserMapper.xml文件,并将内容封装到Configuration对象中,解决问题2和3。

XmlConfigBuilder.java

public class XmlConfigBuilder {
    public static Configuration loadXmlConfig(InputStream inputStream) {
        Configuration configuration = new Configuration();
        try {
            //创建解析XML的SAXReader对象
            SAXReader saxReader = new SAXReader();
            //获取Document对象
            Document document = saxReader.read(inputStream);
            //获取根元素
            Element rootElement = document.getRootElement();
            //获取子元素
            List<Element> list = rootElement.selectNodes("//property");
            //封装数据库连接信息
            for (Element element : list) {
                String name = element.attributeValue("name");
                String value = element.attributeValue("value");
                if ("driver".equalsIgnoreCase(name)) {
                    configuration.setDriver(value);
                }
                if ("url".equalsIgnoreCase(name)) {
                    configuration.setUrl(value);
                }
                if ("username".equalsIgnoreCase(name)) {
                    configuration.setUsername(value);
                }
                if ("password".equalsIgnoreCase(name)) {
                    configuration.setPassword(value);
                }
            }
            //获取mapper元素,这样就可以找到resource对应的XML文件
            List<Element> mapperList = rootElement.selectNodes("//mapper");
            for (Element element : mapperList) {
                String resource = element.attributeValue("resource");
                //封装有关sql信息
                loadSqlConfig(configuration,resource);
            }
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return configuration;
    }

    public static void loadSqlConfig(Configuration configuration,String rousource) throws Exception {
        Map<String, Mapper> mapperMap=configuration.getMapperMap();
        InputStream inputStream = Resources.getResourceAsStream(rousource);
        SAXReader saxReader=new SAXReader();
        Document document = saxReader.read(inputStream);
        Element rootElement = document.getRootElement();
        String namespace = rootElement.attributeValue("namespace");
        List<Element> selectElements = rootElement.selectNodes("//select");
        Mapper mapper;
        for(Element element:selectElements){
            String id =namespace+"."+ element.attributeValue("id");
            String resultType = element.attributeValue("resultType");
            String sql = element.getText();
            mapper=new Mapper();
            mapper.setSql(sql);
            mapper.setResultType(resultType);
            mapperMap.put(id,mapper);
        }
    }
}

而SqlSessionImpl.java完整代码

public class SqlSessionImpl implements SqlSession {

    private Configuration configuration;

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

    @Override
    public <T> List<T> queryList(String sqlId) throws Exception {
        Class.forName(configuration.getDriver());
        Connection connection = DriverManager.getConnection(configuration.getUrl(), configuration.getUsername(), configuration.getPassword());
        Statement statement = connection.createStatement();
        //根据sqlId找到xml中对应的sql内容
        String sql=configuration.getMapperMap().get(sqlId).getSql();
        ResultSet resultSet = statement.executeQuery(sql);
        List<T> list=new ArrayList<>();
        Object obj=null;
        //创建一个空对象,除了new的方式创建对象 还可以用反射创建对象
        //根据类的全限定类名(包名+类名)
        //根据sqlId找到对应的结果集封装对象类型
        String resultType=configuration.getMapperMap().get(sqlId).getResultType();
        Class<?> clazz = Class.forName(resultType);
        //获取ResultSet元数据
        ResultSetMetaData metaData = resultSet.getMetaData();
        //获取ResultSet列名
        List<String> columnNameList=new ArrayList<>();
        for(int i=1;i<=metaData.getColumnCount();i++){
            String columnName = metaData.getColumnName(i);
            columnNameList.add(columnName);
        }
        //获取类中的方法 setXXX getXXX等方法
        Method[] methods = clazz.getMethods();
        while(resultSet.next()){
            obj = clazz.newInstance();
            for(String columnName:columnNameList){
                Object object = resultSet.getObject(columnName);
                for(Method method:methods){
                    String name = method.getName();
                    if(name.equalsIgnoreCase("set"+columnName)){
                        //利用反射执行方法
                        method.invoke(obj,object);
                    }
                }
            }
            list.add((T)obj);
        }
        return list;
    }
}

而SqlSession.java接口相应的变更

public interface SqlSession {
    <T> List<T> queryList(String sqlId) throws Exception;
}

通过创建SqlSessionFactory,调用openSession()获取SqlSession

SqlSessionFactory.java

public class SqlSessionFactory {
    private Configuration configuration;

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

    public SqlSession openSession(){
       SqlSession  sqlSession=new SqlSessionImpl();
       ((SqlSessionImpl) sqlSession).setConfiguration(configuration);
        return sqlSession;
    }
}

通过创建SqlSessionFactoryBuilder,调用build()获取SqlSessionFactory

SqlSessionFactoryBuilder.java

public class SqlSessionFactoryBuilder {
    public SqlSessionFactory build(InputStream inputStream){
        Configuration configuration = XmlConfigBuilder.loadXmlConfig(inputStream);
        SqlSessionFactory sqlSessionFactory=new SqlSessionFactory();
        sqlSessionFactory.setConfiguration(configuration);
        return  sqlSessionFactory;
    }
}

测试代码:

public class SqlSessionFacotryBuilderTest {
    @Test
    public void test() throws Exception {
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder=new SqlSessionFactoryBuilder();
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        List<User> list = sqlSession.queryList("com.company.pojo.UserMapper.queryUserList");
        list.forEach(System.out::println);
    }
}

项目目录如下:

 

 posted on 2019-07-24 22:20  会飞的金鱼  阅读(211)  评论(0)    收藏  举报