自己编写一个简单的ORM框架

创建一个项目,导入所需要的依赖包

这两个包分别是mysql的数据库驱动和c3p0数据库连接池

    <dependencies>
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.2.1</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.23</version>
        </dependency>
    </dependencies>

 

接下来编写c3p0的配置文件(c3p0-config.xml)

<c3p0-config>
    <default-config>
        <!-- 必要参数 -->
        <property name="driverClass">com.mysql.cj.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/books?useSSL=false&amp;serverTimezone=UTC</property>
        <property name="user">root</property>
        <property name="password">root</property>
        <!-- 下面不是必要的参数 -->
        <property name="initialPoolSize">10</property>
        <property name="maxIdleTime">30</property>
        <property name="maxPoolSize">100</property>
        <property name="minPoolSize">10</property>
        <property name="maxStatements">200</property>
    </default-config>
</c3p0-config>

 

创建一个数据库:

/*
 Navicat Premium Data Transfer

 Source Server         : localhost
 Source Server Type    : MySQL
 Source Server Version : 50729
 Source Host           : localhost:3306
 Source Schema         : books

 Target Server Type    : MySQL
 Target Server Version : 50729
 File Encoding         : 65001

 Date: 14/05/2021 18:06:26
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for books
-- ----------------------------
DROP TABLE IF EXISTS `books`;
CREATE TABLE `books`  (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '编号',
  `title` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '书名',
  `price` decimal(10, 2) NULL DEFAULT NULL COMMENT '价格',
  `publishDate` timestamp(0) NULL DEFAULT CURRENT_TIMESTAMP(0) COMMENT '出版日期',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE INDEX `title`(`title`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of books
-- ----------------------------
INSERT INTO `books` VALUES (1, 'Java编程思想', 98.50, '2005-01-02 00:00:00');
INSERT INTO `books` VALUES (2, 'HeadFirst设计模式', 55.70, '2010-11-09 00:00:00');
INSERT INTO `books` VALUES (3, '第一行Android代码', 69.90, '2015-06-23 00:00:00');
INSERT INTO `books` VALUES (4, 'C++编程思想', 88.50, '2004-01-09 00:00:00');
INSERT INTO `books` VALUES (5, 'HeadFirst Java', 55.70, '2013-12-17 00:00:00');
INSERT INTO `books` VALUES (6, '疯狂Android', 19.50, '2014-07-31 00:00:00');

SET FOREIGN_KEY_CHECKS = 1;

 

然后编写我们对应数据库的实体类(Books.java)

public class Books {
    private Long Id;
    private String title;
    private String price;
    private String publishDate;

    public Books() {
    }

    public Books(Long id, String title, String price, String publishDate) {
        Id = id;
        this.title = title;
        this.price = price;
        this.publishDate = publishDate;
    }

    public Long getId() {
        return Id;
    }

    public void setId(Long id) {
        Id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getPrice() {
        return price;
    }

    public void setPrice(String price) {
        this.price = price;
    }

    public String getPublishDate() {
        return publishDate;
    }

    public void setPublishDate(String publishDate) {
        this.publishDate = publishDate;
    }

    @Override
    public String toString() {
        return "Books{" +
                "Id=" + Id +
                ", title='" + title + '\'' +
                ", price='" + price + '\'' +
                ", publishDate='" + publishDate + '\'' +
                '}';
    }
}

 

编写我们的工具类(这里就是我们ORM框架的主要代码实现,主要采用JDBC和反射技术进行实现):

import com.mchange.v2.c3p0.ComboPooledDataSource;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class MyJDBCUtils {
    //创建数据库连接池
    private static ComboPooledDataSource dataSource = new ComboPooledDataSource();

    /*实现查找数据库的功能*/
    public static <T> List<T> query(Class clazz, String sql, Object... args){
        //获得连接对象
        try(Connection conn = dataSource.getConnection()){
            //获得命令对象
            PreparedStatement preparedStatement = conn.prepareStatement(sql);
            //设置占位符参数
            for (int i = 0; i < args.length; i++) {
                preparedStatement.setObject(i+1,args[i]);
            }
            //执行查询,获得一个结果集
            ResultSet resultSet = preparedStatement.executeQuery();
            List<T> list = new ArrayList<>();
            //逐行访问结果集
            while (resultSet.next()){
                //创建java对象来包装一行数据,这个对象就包含多个列了
                Object obj = clazz.newInstance();//反射机制
                //获得该类的所有属性
                Field[] fields = clazz.getDeclaredFields();
                //遍历属性
                for (Field field : fields){
                    String name = field.getName();
                    //获得该列的值
                    Object value = resultSet.getObject(name);
                    //因为属性是private的,所以不能访问,这里我们通过反射技术打开他访问的权限
                    field.setAccessible(true);
                    //给该属性赋值  对象.属性 = 值
                    field.set(obj,castValue(field.getType(),value));
                }
                list.add((T) obj);
            }
            return list;
        }catch (SQLException e){
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
        return null;
    }

    //实现更新数据库的功能
    public static int update(String sql,Object... args) {
        //获得连接对象
        try(Connection conn = dataSource.getConnection()){
            //获得命令对象
            PreparedStatement preparedStatement = conn.prepareStatement(sql);
            //设置占位符参数
            for (int i = 0; i < args.length; i++) {
                preparedStatement.setObject(i+1,args[i]);
            }
            //执行
            int rows = preparedStatement.executeUpdate();
            return rows;
        }catch (SQLException e){
            e.printStackTrace();
        }
        return -1;
    }

    //属性值的类型转换
    public static Object castValue(Class valueType,Object value){
        //就八大基本类型就好,还有其他很多类型,以后再加
        if (valueType == Integer.class){
            return Integer.valueOf(value.toString());
        }
        if (valueType == Byte.class){
            return Byte.valueOf(value.toString());
        }
        if (valueType == Short.class){
            return Short.valueOf(value.toString());
        }
        if (valueType == Long.class){
            return Long.valueOf(value.toString());
        }
        if (valueType == Float.class){
            return Float.valueOf(value.toString());
        }
        if (valueType == Double.class){
            return Double.valueOf(value.toString());
        }
        if (valueType == Boolean.class){
            return Boolean.valueOf(value.toString());
        }
        if (valueType == Character.class){
            //字符类型直接取得他的字符就行
            return value.toString().charAt(0);
        }
        return value.toString();
    }
}

接下来我们对工具类进行测试(MyTest.java):

import java.util.List;

public class MyTest {
    public static void main(String[] args) {
        List<Books> books = MyJDBCUtils.query(Books.class, "select * from books");
        System.out.println(books);
    }
}

 

输出结果:

[Books{Id=1, title='Java编程思想', price='98.50', publishDate='2005-01-02 08:00:00.0'}, Books{Id=2, title='HeadFirst设计模式', price='55.70', publishDate='2010-11-09 08:00:00.0'}, Books{Id=3, title='第一行Android代码', price='69.90', publishDate='2015-06-23 08:00:00.0'}, Books{Id=4, title='C++编程思想', price='88.50', publishDate='2004-01-09 08:00:00.0'}, Books{Id=5, title='HeadFirst Java', price='55.70', publishDate='2013-12-17 08:00:00.0'}, Books{Id=6, title='疯狂Android', price='19.50', publishDate='2014-07-31 08:00:00.0'}]

 

目录结构:

自己编写一个简单的ORM框架

 

上一篇:HMTT——SQLAlchemy映射构建


下一篇:MyBatis 相关概念