1、自己手写ORM框架之创建Connect对象

类图

此类图主要是获取数据库类图,DataBaseOperation是一个接口,定义了数据库的主要操作;AbstractDataBaseOperationFactory是一个抽象类,是所有数据库操作的基类,所有的数据库局要继承次此类,去实现特定的操作;此类图中使用了模板方法。

其相关的代码如下

DataBaseOperation.java
package com.framework.betterorm.Datesource;

import java.sql.Connection;

/**
 *
 * 数据库通用操作
 */
public interface DataBaseOperation {
    /**
     * 数据库连接方法
     */
    Connection connect();

    /**
     * 执行SQL语句(除select)
     */
    int update(String sql, Object object);

    /**
     * 执行select语句
     */
    Object select(String sql, Object o);

}
AbstractDataBaseOperationFactory.java
package com.framework.betterorm.Datesource;


import com.framework.betterorm.reflection.ObjectFields;
import com.framework.betterorm.utils.YamlHelper;
import com.framework.betterorm.parsing.PropertyParser;

import java.sql.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

public abstract class AbstractDataBaseOperationFactory implements DataBaseOperation {
    public static String databaseType;
    /**
     * 声明一个 Connection类型的静态属性,用来缓存一个已经存在的连接对象
     */
    public static Connection conn = null;
    /**
     * 用户名
     */
    protected static String username;
    /**
     * 密码
     */
    protected static String password;
    /**
     * 是否自动提交事务
     */
    protected static boolean autoCommit = false;
    protected static String url;

    static {

        config(Objects.requireNonNull(AbstractDataBaseOperationFactory.class.getClassLoader().getResource("DataBaseConfig.yml")).getFile());
    }

    /**
     * 获取文件的连接信息,采用最简洁的yaml文件
     */
    private static void config(String file) {
        System.out.println("config");
        if (YamlHelper.fileRead(file) == null) {
            return;
        }
        Map<String, Object> infoMap = (Map<String, Object>) YamlHelper.fileRead(file).get("Datasource");
        if (infoMap.size() <= 0) {
            return;
        }
        //获取用户名
        username = String.valueOf(infoMap.get("username")).trim();
        //获取密码
        password = String.valueOf(infoMap.get("password")).trim();
        //设置是否自动提交
        autoCommit = false;
        if (infoMap.get("autoCommit") != null) {
            autoCommit = (boolean) infoMap.get("autoCommit");
        }
        //获取连接字符串
        url = String.valueOf(infoMap.get("url")).trim();
        databaseType = url.split(":")[1];

    }

    /**
     * 释放资源
     **/
    public static void release(Object cloaseable) {
        if (cloaseable != null) {
            if (cloaseable instanceof ResultSet) {
                ResultSet rs = (ResultSet) cloaseable;
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (cloaseable instanceof Statement) {
                Statement st = (Statement) cloaseable;
                try {
                    st.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if (cloaseable instanceof Connection) {
                Connection c = (Connection) cloaseable;
                try {
                    c.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    /**
     * 回滚事务
     */
    private static void rollback(Connection c) {
        if (c != null && !autoCommit) {
            try {
                c.rollback();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    private static Object typeof(Object o) {
        Object r = o;

        if (o instanceof Timestamp) {
            return r;
        }
        // 将 java.util.Date 转成 java.session.Date
        if (o instanceof java.util.Date) {
            java.util.Date d = (java.util.Date) o;
            r = new Date(d.getTime());
            return r;
        }
        // 将 Character 或 char 变成 String
        if (o instanceof Character || o.getClass() == char.class) {
            r = String.valueOf(o);
            return r;
        }
        return r;
    }

    public String getInstance() {
        return this.getClass().getSimpleName();
    }

    /**
     * 有子类实现
     */
    @Override
    public abstract Connection connect();

    /**
     * 专门检查缓存的连接是否不可以被使用 ,不可以被使用的话,就返回 true
     */
    protected boolean invalid() {
        if (conn != null) {
            try {

                //isValid方法是判断Connection是否有效,如果连接尚未关闭并且仍然有效,则返回true

                if (conn.isClosed() || !conn.isValid(3)) {
                    return true;

                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
            /**
             * conn 既不是 null 且也没有关闭 ,且 isValid 返回 true,说明是可以使用的 (返回false)
             */
            return false;
        } else {
            return true;

        }
    }

    /**
     * 设置是否自动提交事务
     **/
    public void transaction() {
        try {
            conn.setAutoCommit(autoCommit);
        } catch (SQLException e) {
            System.out.println("设置事务的提交方式为 : " + (autoCommit ? "自动提交" : "手动提交") + " 时失败: " + e.getMessage());
        }
    }

    /**
     * 提交事务
     */
    private void commit(Connection c) {
        if (c != null && !autoCommit) {
            try {
                c.commit();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

    }


}
MySQLDataSource.java
package com.framework.betterorm.Datesource;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class MySQLDataSource extends AbstractDataBaseOperationFactory {

    @Override
    public Connection connect() {
        if (invalid()) {
            try {
                //载入数据库驱动
                Class.forName("com.mysql.cj.jdbc.Driver");
                //建立连接
                conn = DriverManager.getConnection(url, username, password);
                System.out.println("Mysql 已连接");
            } catch (SQLException e) {
                System.out.println("建立 " + conn + " 数据库连接失败 , " + e.getMessage());
            } catch (ClassNotFoundException e) {
                System.out.println("MySql驱动加载失败:" + e.getMessage());
            }

        }
        return conn;
    }
}

其他数据库相关类如下

OracleDataSource.java
package com.framework.betterorm.Datesource;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class OracleDataSource extends AbstractDataBaseOperationFactory {
    @Override
    public Connection connect() {
        if (invalid()) {
            try {
                Class.forName("oracle.jdbc.driver.OracleDriver");
                //建立连接
                conn = DriverManager.getConnection(url, username, password);
                System.out.println("Mysql 已连接");
            } catch (SQLException e) {
                System.out.println("建立 " + conn + " 数据库连接失败 , " + e.getMessage());
            } catch (ClassNotFoundException e) {
                System.out.println("Oracle驱动加载失败:" + e.getMessage());

            }
        }
        return conn;

    }
}

 

获取conn对象

当有不同的数据库事我们需要大量的的选择判断,去决定将要实例化的类。在这里我们使用策略模式+单例模式+java反射机制去决定实例化那个类

定义数据库类型的枚举

DataBaseTypeEnum.java
package com.framework.betterorm.Datesource;

/**
 * @author 王彪
 * @date 2019.5.28
 * 数据库类型
 */
public enum DataBaseTypeEnum {
    /**
     * mysql
     */
    MYSQL("mysql", "com.framework.betterorm.Datesource.MySQLDataSource"),
    /**
     * SQLServer
     */
    MSSQL("sqlserver", "com.framework.betterorm.Datesource.MsSQLDatasource"),
    /**
     * oracle
     */
    oracle("oracle", "com.framework.betterorm.Datesource.OracleDataSource");
    /**
     * 数据库类型
     */
    private String type;
    /**
     * 对应操作的实体类
     */
    private String clazz;

    DataBaseTypeEnum(String type, String clazz) {
        this.type = type;
        this.clazz = clazz;
    }

    public String getType() {
        return type;
    }

    public String getClazz() {
        return clazz;
    }
}

定义单例模式类

CommonSingleton.java
package com.framework.betterorm.common;


import com.framework.betterorm.session.SqlType;

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

public class CommonSingleton {

    /**
     * 数据库操作类型Map
     */
    private static Map<String, String> sqlTypeMap = new HashMap<>();

    static {

        for (SqlType sqlType : SqlType.values()) {
            sqlTypeMap.put(sqlType.getAnnotation(), sqlType.getMethod());
        }
    }

    private CommonSingleton() {
    }

    public static CommonSingleton getInstance() {
        return CommonSingleton.SingletonInstance.instance;
    }


    /**
     * 根据注解取得对应的操作方法
     */
    public String sqlTypeStratgy(String annotation) {
        return sqlTypeMap.get(annotation);
    }

    private static class SingletonInstance {
        static CommonSingleton instance = new CommonSingleton();
    }
}

定义策略模式类

此类就只有一个方法,根据配置文件去实例化相关类然后去实例化connection

package com.framework.betterorm.common;


import com.framework.betterorm.Datesource.DataBaseTypeEnum;
import com.framework.betterorm.session.SqlType;

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

public class CommonSingleton {
    /**
     * 数据库类型map
     */
    private static Map<String, String> dataBaseTypeMap = new HashMap<>();
    

    static {
        for (DataBaseTypeEnum dataBaseTypeEnum : DataBaseTypeEnum.values()) {
            dataBaseTypeMap.put(dataBaseTypeEnum.getType(), dataBaseTypeEnum.getClazz());
        }
    }

    private CommonSingleton() {
    }

    public static CommonSingleton getInstance() {
        return CommonSingleton.SingletonInstance.instance;
    }

    /**
     * 根据数据库类型取得对应操作类
     */
    public String dataBaseOperateStrategy(String type) {
        return dataBaseTypeMap.get(type);
    }

    
    private static class SingletonInstance {
        static CommonSingleton instance = new CommonSingleton();
    }
}

 此时一个Connection,对象就实例化完成。可以通过此对象去进行操作数据库了。

配置文件如下:

DataBaseConfig.yml

Datasource:
  username: root
  password: 123456
  url: jdbc:mysql://127.0.0.1:3306/test?useSSL=true&serverTimezone=GMT&characterEncoding=utf8
 # url: jdbc:sqlserver://localhost:1433;databaseName=test
  #url: jdbc:postgresql://localhost/dbname
  #url:  jdbc:db2://127.0.0.1:50000/dbname
  #url:  jdbc:sybase:Tds:localhost:5007/dbname
  #url: jdbc:oracle:thin:@127.0.0.1:1521:test
  autoCommit: false

读取此文件的相关类如下

package com.framework.betterorm.utils;

import org.yaml.snakeyaml.Yaml;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Map;

public class YamlHelper {
    public static Map<String, Object> fileRead(String filePath) {
        Yaml yaml = new Yaml();
        File file = new File(filePath);
        try {
            if (yaml.load(new FileInputStream(file)) != null) {
                return yaml.load(new FileInputStream(file));
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值