手写简易Mybatis框架


详细jar包见我的资源,免费下载。

一、该框架局限性:

  • 数据库表列名必须是varchar。
  • 本手写框架只实现了JDBC的事务管理器和UNPOOLED的数据源属性。
  • 本手写框架仅支持insert操作和单条件查询。

二、框架结构:

在这里插入图片描述

三、实现思路:

在这里插入图片描述

四、实现类:

Resources工具类:

package org.god.ibatis.util;

import java.io.InputStream;

/**
 * 工具类,完成类路径中资源的加载
 * @author 姓蔡小朋友
 * @since 1.0
 * @version 1.0
 */
public class Resources {
    /**
     * 工具类中的构造方法要私有化
     */
    private Resources() {}

    /**
     * 从类路径中加载资源,工具类中的方法要是静态的
     * @param resource 放在类路径中的资源文件
     * @return 返回一个指向资源文件的输入流
     */
    public static InputStream getResourcesAsStream(String resource){
        return ClassLoader.getSystemClassLoader().getResourceAsStream(resource);
    }
}

Const常量类:

package org.god.ibatis.core;

/**
 * 整个框架的常量类,保证OCP原则,修改时不必修改底层代码
 * @author 姓蔡小朋友
 * @since 1.0
 * @version 1.0
 */
public class Const {
    public static final String UN_POOLED_DATASOURCE = "UNPOOLED";
    public static final String POOLED_DATASOURCE = "POOLED";
    public static final String JNDI_DATASOURCE = "JNDI";
    public static final String JDBC_TRANSACTION = "JDBC";
    public static final String MANAGED_TRANSACTION = "MANAGED";
}

MappedStatement POJO类:

package org.god.ibatis.core;

/**
 * POJO类
 * 一个MappedStatement对象封装了一个SQL标签的所有信息:<insert>||<update>||<delete>||<select>
 * @author 姓蔡小朋友
 * @since 1.0
 * @version 1.0
 */
public class MappedStatement {
    /**
     * sql语句
     */
    private String sql;
    /**
     * 入参类型
     */
    private String parameterType;
    /**
     * 结果集类型
     */
    private String resultType;

    public MappedStatement(String sql, String parameterType, String resultType) {
        this.sql = sql;
        this.parameterType = parameterType;
        this.resultType = resultType;
    }

    public MappedStatement() {
    }

    public String getSql() {
        return sql;
    }

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

    public String getParameterType() {
        return parameterType;
    }

    public void setParameterType(String parameterType) {
        this.parameterType = parameterType;
    }

    public String getResultType() {
        return resultType;
    }

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

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

SqlSessionFactoryBuilder类:

package org.god.ibatis.core;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.god.ibatis.util.Resources;

import javax.sql.DataSource;
import java.io.InputStream;
import java.util.*;

/**
 * SqlSessionFactory构建器类
 * 通过SqlSessionFactoryBuilder的build方法解析SqlMapConfig.xml文件
 * @author 姓蔡小朋友
 * @since 1.0
 * @version 1.0
 */
public class SqlSessionFactoryBuilder {
    /**
     *无参数构造方法,用于创建对象
     */
    public SqlSessionFactoryBuilder() {
    }
    /**
     * 解析SqlMapConfig.xml文件,构造SqlSessionFactory对象,本类后面的三个get方法都是为该方法服务的
     * @param in 指向SqlMapConfig.xml文件的输入流
     * @return 返回SqlSessionFactory对象
     */
    public SqlSessionFactory build(InputStream in){
        SqlSessionFactory factory = null;
        try {
            //解析SqlMapConfig.xml核心配置文件
            SAXReader reader = new SAXReader();
            Document document = reader.read(in);
            //获取environments标签及其属性
            Element environments = (Element) document.selectSingleNode("/configuration/environments");
            String defaultId = environments.attributeValue("default");
            //获取environment标签及其子标签transactionManager、dataSource
            Element environment = (Element) document.selectSingleNode("/configuration/environments/environment[@id='" + defaultId + "']");
            Element transactionElt = environment.element("transactionManager");
            Element dataSourceElt = environment.element("dataSource");
            //获取所有Mapper.xml文件并加入到SQLMapperXMLPathList集合中
            List<String> SQLMapperXMLPathList = new ArrayList<>();
            List<Node> mappers = document.selectNodes("//mapper");
            for (Node Tmapper : mappers) {
                Element mapper = (Element)Tmapper;
                String resource = mapper.attributeValue("resource");
                SQLMapperXMLPathList.add(resource);
            }
            //获取数据源,为什么要获取数据源?因为创建事务管理器需要数据源
            DataSource dataSource = getDataSource(dataSourceElt);
            //获取事务管理器
            Transaction transaction = getTransaction(transactionElt,dataSource);
            //获取SQL集合
            Map<String,MappedStatement> mappedStatements = getMappedStatements(SQLMapperXMLPathList);
            //传入事务管理器和SQL集合,创建SqlSessionFactory
            factory = new SqlSessionFactory(transaction,mappedStatements);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return factory;
    }

    /**
     * 解析所有Mapper.xml文件,然后构建Mapper集合
     * @param SQLMapperXMLPathList 所有Mapper.xml文件名
     * @return SQL集合
     */
    private Map<String, MappedStatement> getMappedStatements(List<String> SQLMapperXMLPathList) {
        //存放所有xml文件的所有SQL语句的信息
        Map<String,MappedStatement> mappedStatements = new HashMap<>();
        //遍历所有Mapper.xml文件并添加所有sql标签内容到SQL集合mappedStatements中
        for (String SQLMapperXMLPath : SQLMapperXMLPathList) {
            try {
                SAXReader reader = new SAXReader();
                Document document = reader.read(Resources.getResourcesAsStream(SQLMapperXMLPath));
                //获取该Mapper.xml文件下的mapper标签
                Element mapper = (Element)document.selectSingleNode("mapper");
                //获取mapper标签的namespace属性
                String namespace = mapper.attributeValue("namespace");
                //获取mapper标签下所有sql标签
                List<Element> elements = mapper.elements();
                //遍历sql标签内容添加到SQL集合mappedStatements中
                for (Element element : elements) {
                    //获取属性
                    String id = element.attributeValue("id");
                    String sqlid = namespace+"."+id;//拼接,区分不同mapper.xml文件下相同id的标签,防止id冲突
                    String parameterType = element.attributeValue("parameterType");
                    String resultType = element.attributeValue("resultType");
                    //获取标签内容(sql语句)
                    String sql = element.getText().trim();
                    //将单个SQL标签的信息封装进我们创建的POJO对象中
                    MappedStatement mappedStatement = new MappedStatement(sql,parameterType,resultType);
                    //将该SQL标签的内容添加到SQL集合mappedStatements中
                    mappedStatements.put(sqlid,mappedStatement);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return mappedStatements;
    }

    /**
     * 获取事务管理器对象
     * @param transactionElt 事务管理器标签元素<transactionManager>
     * @param dataSource 数据源对象
     * @return Transaction
     */
    private Transaction getTransaction(Element transactionElt, DataSource dataSource) {
        //存储创建的事务管理器对象
        Transaction transaction = null;
        //JDBC||MANAGED,根据不同属性值创建不同事务管理器对象
        String type = transactionElt.attributeValue("type").trim().toUpperCase();
        if (Const.JDBC_TRANSACTION.equals(type)) {
            transaction = new JdbcTransaction(dataSource,false);//默认开启事务
        }
        if (Const.MANAGED_TRANSACTION.equals(type)) {
            transaction = new ManagedTransaction();
        }
        return transaction;
    }

    /**
     * 获取数据源对象
     * @param dataSourceElt 数据源标签元素<dataSource>
     * @return DataSource
     */
    private DataSource getDataSource(Element dataSourceElt) {
        //存储创建的数据源对象
        DataSource dataSource = null;
        //获取所有property标签
        Map<String,String> map= new HashMap<>();
        //获取所有property标签
        List<Element> propertyElts = dataSourceElt.elements("property");
        //遍历所有property标签得到属性值并加入到map集合中,属性值就是数据库登录信息
        for (Element propertyElt : propertyElts) {
            String name = propertyElt.attributeValue("name");
            String value = propertyElt.attributeValue("value");
            map.put(name,value);
        }
        //UNPOOLED||POOLED||JNDI,根据不同属性值创建不同数据源对象
        String type = dataSourceElt.attributeValue("type").trim().toUpperCase();
        if (Const.UN_POOLED_DATASOURCE.equals(type)) {
            dataSource = new UnPooledDataSource(map.get("driver"),map.get("url"),map.get("username"),map.get("password"));
        }
        if (Const.POOLED_DATASOURCE.equals(type)) {
            dataSource = new PooledDataSource();
        }
        if (Const.JNDI_DATASOURCE.equals(type)) {
            dataSource = new JNDIDataSource();
        }
        return dataSource;
    }
}

SqlSessionFactory类:

package org.god.ibatis.core;

import javax.sql.DataSource;
import java.util.Map;

/**
 * 一个数据库对应一个SqlSessionFactory对象,对象中应存储:用户选择的事务管理器类型,用户针对该数据库编写的所有SQL语句,数据库连接信息
 * 通过SqlSessionFactory对象可以获取SqlSession对象(开启会话)
 * 一个SqlSessionFactory对象可获取多个SqlSession会话对象
 * @author 姓蔡小朋友
 * @since 1.0
 * @version 1.0
 */
public class SqlSessionFactory {
    /**
     * 事务管理器属性<transactionManager>,用来管理事务提交、回滚、关闭的
     * 这里不确定用户到底是用JDBC还是MANAGED,所以我们使用接口,用户使用哪个就多态指向哪个实现类
     */
    private Transaction transaction;
    /**
     * 存放所有SQL语句的Map集合
     * key是sqlId
     * value是sqlId对应的SQL标签的信息(属性,标签内容),用MappedStatment对象封装
     */
    private Map<String,MappedStatement> mappedStatements;
    /**
     * 这里为了自动连接数据库,应该还有一个数据库连接信息<dataSource>,但是这个这些信息在transaction实现类中已经创建了,所以这里我们就不用再创建了
     */
    //private DataSource dataSource;
    /**
     * 无参构造方法和有参构造方法
     */
    public SqlSessionFactory() {
    }
    public SqlSessionFactory(Transaction transaction, Map<String, MappedStatement> mappedStatements) {
        this.transaction = transaction;
        this.mappedStatements = mappedStatements;
    }

    /**
     * 获取SQL会话对象SqlSession
     * @return
     */
    public SqlSession openSession(){
        //开启连接,给connection对象赋值
        transaction.openConnection();
        //我们还需要把transaction传给sqlSession,方便sqlSession调用transaction的getConnection()方法
        //我们需要把我们的SQL集合传给sqlSession,这样sqlSession才能执行sql语句
        SqlSession sqlSession = new SqlSession(this);
        return sqlSession;
    }

    public Transaction getTransaction() {
        return transaction;
    }

    public Map<String, MappedStatement> getMappedStatements() {
        return mappedStatements;
    }
}

SqlSession类:

package org.god.ibatis.core;

import java.lang.reflect.Method;
import java.sql.*;
import java.util.Locale;

/**
 * 专门负责执行SQL语句的对象
 * @author 姓蔡小朋友
 * @since 1.0
 * @version 1.0
 */
public class SqlSession {
    /**
     * SqlSessionFactory的openSqlSession()方法会创建SqlSession对象,
     * 并将SqlSessionFactory及其属性事务管理器对象transaction,SQL语句集合mappedStatements传过来
     */
    private SqlSessionFactory factory;

    public SqlSession(SqlSessionFactory factory) {
        this.factory = factory;
    }

    /**
     * 执行insert语句
     * @param sqlId sql语句的Id,sqlId = namespace + 标签id
     * @param pojo 用户想插入的数据,是用户自己传的,Object类型表示可以接受任意类型数据
     * @return
     */
    public Integer insert(String sqlId,Object pojo){
        int count = 0;
        try {
            //获取连接,见UnPooledDataSource类的getConnection()方法,就是JDBC获取连接的方法
            Connection connection = factory.getTransaction().getConnection();
            //get(sqlId)是map集合的方法,获取到sqlId对应的MappedStatement对象,通过MappedStatement对象的getSql()方法获得对象内存放的sql语句
            String oldsql=factory.getMappedStatements().get(sqlId).getSql();
            //将原来的insert into student(name,email,age) values(#{name},#{email},#{age})使用正则表达式
            //替换成insert into student(name,email,age) values(?,?,?)
            String sql = oldsql.replaceAll("#\\{[a-zA-Z0-9_$]*}","?");
            PreparedStatement ps = connection.prepareStatement(sql);
            //这里的关键在于,你预先不知道用预编译的SQL里有几个?,也不知道用户传来的参数与哪个?对应
            //给?传值,并解析sql语句需要传值的位置和需要传值的参数名
            int fromIndex = 0;
            int index = 1;//表示这是第几个问号,即需要传值的位置
            while(true){
                int jingHaoIndex = oldsql.indexOf("#",fromIndex);
                if(jingHaoIndex<0){
                    break;//退出死循环
                }
                int youKuoHaoIndex = oldsql.indexOf("}",fromIndex);
                String propertyName = oldsql.substring(jingHaoIndex+2,youKuoHaoIndex).trim();//第index个问号中占位符的值
                fromIndex = youKuoHaoIndex+1;
                //已知属性名propertyName,通过调用用户自定义pojo类的get方法获取属性值
                //这里使用拼接方法名的方式获取相应的get方法得到要给该?传的参数,getMethodName就是我们拼成的getXXX()方法
                String getMethodName = "get"+propertyName.toUpperCase().charAt(0)+propertyName.substring(1);
                //反射执行方法
                Method getMethod = pojo.getClass().getDeclaredMethod(getMethodName);
                Object propertyValue = getMethod.invoke(pojo);
                ps.setString(index,propertyValue.toString());
                index++;
            }
            //执行sql
            count = ps.executeUpdate();
        } catch (Exception throwables) {
            throwables.printStackTrace();
        }
        return count;
    }
    /**
     * 执行查询语句,返回一个对象,只能返回一行
     * @param sqlId
     * @param param
     * @return
     */
    public Object selectOne(String sqlId,Object param){
        Object obj = null;
        try {
            //获取连接
            Connection connection = factory.getTransaction().getConnection();
            //get(sqlId)是map集合的方法,获取到sqlId对应的MappedStatement对象,通过MappedStatement对象的getSql()方法获得对象内存放的sql语句
            MappedStatement mappedStatement = factory.getMappedStatements().get(sqlId);
            //sql语句
            String oldsql = mappedStatement.getSql();
            String sql = oldsql.replaceAll("#\\{[a-zA-Z0-9_$]*}","?").trim();
            PreparedStatement ps = connection.prepareStatement(sql);
            //给占位符传值,这里只有一个占位符
            ps.setString(1,param.toString());
            ResultSet resultSet = ps.executeQuery();
            //要封装的结果类型
            String resultType = mappedStatement.getResultType();
            if (resultSet.next()) {
                //反射获取class
                Class resultTypeClass = Class.forName(resultType);
                //调用无参构造方法创建对象
                obj = resultTypeClass.newInstance();
                //给属性赋值
                //这里的关键在于SQL执行返回了一列数据,但是这列数据包含什么内容我们预先不知道(不知道列名),各个数据应该传给POJO对象的哪个属性是关键
                ResultSetMetaData rsmd = resultSet.getMetaData();
                //获取列数
                int columnCount = rsmd.getColumnCount();
                for (int i = 1; i <= columnCount; i++) {
                    //根据列名拼接set的方式获得set方法,给POJO对象的属性赋值
                    String propertyName = rsmd.getColumnName(i);
                    //这里的setMethodName就是我们拼接成的setXXX()方法
                    String setMethodName =  "set"+propertyName.toUpperCase().charAt(0)+propertyName.substring(1);
                    Method setMethod = resultTypeClass.getDeclaredMethod(setMethodName,String.class);
                    //调用我们拼接的set方法,传入该列对应的查询结果
                    setMethod.invoke(obj,resultSet.getString(propertyName));
                }
            }
        } catch (Exception throwables) {
            throwables.printStackTrace();
        }
        return obj;
    }

    /**
     * 获取factory的属性transaction,通过该事务管理器transaction的commit()方法提交事务
     */
    public void commit(){
        factory.getTransaction().commit();
    }
    /**
     * 获取factory的属性transaction,通过该事务管理器transaction的commit()方法回滚事务
     */
    public void rollback(){
        factory.getTransaction().rollback();
    }
    /**
     * 获取factory的属性transaction,通过该事务管理器transaction的commit()方法关闭事务
     */
    public void close(){
        factory.getTransaction().close();

    }
}

Transaction接口:

package org.god.ibatis.core;


import java.sql.Connection;

/**
 * 事务管理器接口,用来管理事务提交、回滚、关闭的
 * 所有事务管理器(JDBC,MANAGED)都应该遵循该接口
 * @author 姓蔡小朋友
 * @since 1.0
 * @version 1.0
 */
public interface Transaction {
    /**
     * 提交事务
     */
    public void commit();
    /**
     * 回滚事务
     */
    public void rollback();
    /**
     * 关闭事务
     */
    public void close();
    /**
     * 开启connection连接
     */
    public void openConnection();
    /**
     * 获取Transaction的connection连接对象
     */
    public Connection getConnection();
}

JdbcTransaction类:该框架已实现

package org.god.ibatis.core;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

/**
 * JDBC事务管理器,用JDBC来管理事务提交、回滚、关闭的,实现Transaction接口
 * @author 姓蔡小朋友
 * @since 1.0
 * @version 1.0
 */
public class JdbcTransaction implements Transaction{
    /**
     * 数据源属性<dataSource>,封装了用户登录数据库的信息
     * 这里不确定用户到底是用POOLED、UNPOOLED、JNDI,所以我们使用接口,用户使用哪个就多态指向哪个实现类
     */
    private DataSource dataSource;
    /**
     * 事务是否自动提交标志
     * true自动提交
     * false手动提交
     */
    private boolean autoCommit;
    /**
     * 数据库连接对象,通过openConnection方法给connection赋值
     */
    private Connection connection;
    /**
     * 根据数据源和是否自动提交标志创建事务管理器
     * @param dataSource 数据源,有三种实现类
     * @param autoCommit 是否自动提交标志
     */
    public JdbcTransaction(DataSource dataSource, boolean autoCommit) {
        this.dataSource = dataSource;
        this.autoCommit = autoCommit;
    }
    /**
     * 获取dataSource的连接对象
     */
    public void openConnection(){
        if (connection == null) {
            try {
                connection = dataSource.getConnection();//这里调用的dataSource接口的getConnection,他有三个实现类
                //开启事务
                connection.setAutoCommit(autoCommit);
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
    /**
     * 方便其他类使用JdbcTransaction这个类的对象时获取JdbcTransaction下的connection
     * @return 本类中封装的connection
     */
    @Override
    public Connection getConnection() {
        return connection;
    }
    /**
     * 事务提交
     */
    @Override
    public void commit() {
        try {
            connection.commit();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
    /**
     * 事务回滚
     */
    @Override
    public void rollback() {
        try {
            connection.rollback();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
    /**
     * 事务关闭
     */
    @Override
    public void close() {
        try {
            connection.close();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
}

ManagedTransaction类:该框架未实现

package org.god.ibatis.core;

import java.sql.Connection;

/**
 * MANAGED事务管理器,用来管理事务提交、回滚、关闭的,实现Transaction接口
 * 因为我们的godbatis比较简单,所以我们不对这个复杂的类进行实现。
 * @author 姓蔡小朋友
 * @since 1.0
 * @version 1.0
 */
public class ManagedTransaction implements Transaction{
    @Override
    public void commit() {

    }

    @Override
    public void rollback() {

    }

    @Override
    public void close() {

    }

    @Override
    public void openConnection() {

    }

    @Override
    public Connection getConnection() {
        return null;
    }
}

UnPooledDataSource类:该框架已实现

package org.god.ibatis.core;

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.logging.Logger;

/**
 * 数据源实现类:UNPOOLED
 * 该实现类特点:不使用连接池,每次都新建connection对象
 * javax.sql.DataSource是JDK自带的数据源接口,所以我们不用再去写一个像Transaction一样的接口
 * @author 姓蔡小朋友
 * @since 1.0
 * @version 1.0
 */
public class UnPooledDataSource implements javax.sql.DataSource{
    private String url;
    private String username;
    private String password;
    /**
     * 创建一个数据源对象
     * @param driver
     * @param url
     * @param username
     * @param password
     */
    public UnPooledDataSource(String driver, String url, String username, String password) {
        try {
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        this.url = url;
        this.username = username;
        this.password = password;
    }
    @Override
    public Connection getConnection() throws SQLException {
        Connection connection = DriverManager.getConnection(url,username,password);
        return connection;
    }

    @Override
    public Connection getConnection(String username, String password) throws SQLException {
        return null;
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        return null;
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return false;
    }

    @Override
    public PrintWriter getLogWriter() throws SQLException {
        return null;
    }

    @Override
    public void setLogWriter(PrintWriter out) throws SQLException {

    }

    @Override
    public void setLoginTimeout(int seconds) throws SQLException {

    }

    @Override
    public int getLoginTimeout() throws SQLException {
        return 0;
    }

    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
        return null;
    }
}

PooledDataSource类:该框架未实现

package org.god.ibatis.core;

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.logging.Logger;
/**
 * 数据源实现类:POOLED
 * 该实现类特点:使用连接池,每次都从数据库连接池获取connection对象
 * @author 姓蔡小朋友
 * @since 1.0
 * @version 1.0
 */
public class PooledDataSource implements javax.sql.DataSource{
    @Override
    public Connection getConnection() throws SQLException {
        return null;
    }

    @Override
    public Connection getConnection(String username, String password) throws SQLException {
        return null;
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        return null;
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return false;
    }

    @Override
    public PrintWriter getLogWriter() throws SQLException {
        return null;
    }

    @Override
    public void setLogWriter(PrintWriter out) throws SQLException {

    }

    @Override
    public void setLoginTimeout(int seconds) throws SQLException {

    }

    @Override
    public int getLoginTimeout() throws SQLException {
        return 0;
    }

    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
        return null;
    }
}

JNDIDataSource类:该框架未实现

package org.god.ibatis.core;

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.logging.Logger;
/**
 * 数据源实现类:JNDI
 * 该实现类特点:使用第三方数据库连接池
 * @author 姓蔡小朋友
 * @since 1.0
 * @version 1.0
 */
public class JNDIDataSource implements javax.sql.DataSource {
    @Override
    public Connection getConnection() throws SQLException {
        return null;
    }

    @Override
    public Connection getConnection(String username, String password) throws SQLException {
        return null;
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        return null;
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return false;
    }

    @Override
    public PrintWriter getLogWriter() throws SQLException {
        return null;
    }

    @Override
    public void setLogWriter(PrintWriter out) throws SQLException {

    }

    @Override
    public void setLoginTimeout(int seconds) throws SQLException {

    }

    @Override
    public int getLoginTimeout() throws SQLException {
        return 0;
    }

    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
        return null;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

姓蔡小朋友

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值