一起来写个SQLite ORM数据库框架(下)

2024-06-10 08:32

本文主要是介绍一起来写个SQLite ORM数据库框架(下),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

接上一节 一起来写个SQLite ORM数据库框架(上) 这节讲下代码实现。
首先有4个注解类:表名注解-Table、主键注解-PrimaryKey、列注解-Column、非数据库字段注解-NotDBColumn。因为篇幅的原因 这里只单独看看新增的实现 其他都类似

列注解类

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Column {String value() default "";String defaultValue() default "";
}

列注解对应的对象实体类(ColumnEntity ):

public class ColumnEntity {/*** 实体类中的属性字段*/private Field field;private String columnName;private String defaultValue;/*** 获取指定对象的当前字段的值* @param entity    获取字段值的对象* @return*/public Object getValue(Object entity) {if(entity != null) {try {//设置属性是可以访问的field.setAccessible(true);return field.get(entity);} catch (IllegalArgumentException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}return null;}/*** 设置指定对象的当前字段的值* @param entity    获取字段值的对象* @return*/public void setValue(Object entity, Cursor cursor) throws Exception{Class<?> fieldType = field.getType();try {int columnIdx = cursor.getColumnIndex(columnName);if(columnIdx == -1) {//当前游标中没有该字段的值return;}field.setAccessible(true);if(fieldType==int.class||fieldType==Integer.class) {field.set(entity, cursor.getInt(columnIdx));return;}if(fieldType==char.class||fieldType==String.class){field.set(entity, cursor.getString(columnIdx));return;}if(fieldType==long.class||fieldType==Long.class){field.set(entity, cursor.getLong(columnIdx));return;}if(fieldType==float.class||fieldType==Float.class){field.set(entity, cursor.getFloat(columnIdx));return;}if(fieldType==double.class||fieldType==Double.class){field.set(entity, cursor.getDouble(columnIdx));return;}} catch (Exception e) {throw e;}}//    public Field getField() {
//        return field;
//    }public void setField(Field field) {this.field = field;}public String getColumnName() {return columnName;}public void setColumnName(String columnName) {this.columnName = columnName;}public String getDefaultValue() {return defaultValue;}public void setDefaultValue(String defaultValue) {this.defaultValue = defaultValue;}
}

解析注解映射对象管理类(TableEntityManager ):

public class TableEntityManager {/*** 每张表的相关信息缓存集合*/private static HashMap<Object, TableEntity> mTableMap = new HashMap<Object, TableEntity>();/*** 获取EntityTable对象*/public static <T> TableEntity getTableEntity(T entity) {return getTableEntity(entity.getClass());}public static <T> TableEntity getTableEntity(Class<?> mClass) {if(mTableMap.containsKey(mClass)) {return mTableMap.get(mClass);} else {return createTableEntity(mClass);}}public static TableEntity createTableEntity(Class<?> mClass) {TableEntity tableEntity = new TableEntity();//设置表名setTableName(tableEntity,mClass);//设置主键和列setColumnList(tableEntity,mClass);mTableMap.put(mClass, tableEntity);return tableEntity;}/*** 解析注解设置表名*/public static void setTableName(TableEntity tableEntity,Class<?> mClass) {Table table = mClass.getAnnotation(Table.class);if(null==table||TextUtils.isEmpty(table.value())) {tableEntity.setTableName(mClass.getSimpleName());}tableEntity.setTableName(table.value());}/*** 解析注解设置主键(PrimaryKeyEntity)*/public static boolean setPrimaryKey(TableEntity tableEntity,Field field){PrimaryKey primaryKey = field.getAnnotation(PrimaryKey.class);if(null == primaryKey) {return false;}if(primaryKey.isAutoGenerate() && field.getType()!=long.class && field.getType()!=int.class){throw new RuntimeException("自增长主键字段类型不正确,请设置自增长字段类型为long或者int");}PrimaryKeyEntity primaryKeyEntity = new PrimaryKeyEntity();primaryKeyEntity.setField(field);if(TextUtils.isEmpty(primaryKey.value())) {//没有通过注解设置列名,默认取字段名称为列名primaryKeyEntity.setColumnName(field.getName());} else {primaryKeyEntity.setColumnName(primaryKey.value());}primaryKeyEntity.setAutoGenerate(primaryKey.isAutoGenerate());//获取是否自动增长tableEntity.setPrimaryKey(primaryKeyEntity);return true;}/*** 解析注解获得字段列名和默认值并封装到 ColumnEntity*/public static void setColumnList(TableEntity tableEntity,Class<?> mClass) {Field[] fields = mClass.getDeclaredFields();List<ColumnEntity> columnList = new ArrayList<ColumnEntity>();ColumnEntity columnEntity = null;for(Field field:fields){if (Modifier.isStatic(field.getModifiers())) {//过滤掉static静态字段continue;}if(field.getType() == Object.class) {//过滤掉非基本类型字段continue;}NotDBColumn notDbColumn = field.getAnnotation(NotDBColumn.class);if(null != notDbColumn) {//非数据库字段不作处理continue;}if(null==tableEntity.getPrimaryKey()){ //判断是否有主键注释 并设置主键if(setPrimaryKey(tableEntity,field)){continue;}}//获取每个字段的注解Column column = field.getAnnotation(Column.class);columnEntity = new ColumnEntity();columnEntity.setField(field);// 解析注解设置列名,默认取字段名称为列名String columnName = field.getName();if(column != null) {if (!TextUtils.isEmpty(column.value())) {columnName = column.value();}if(!TextUtils.isEmpty(column.defaultValue())){columnEntity.setDefaultValue(column.defaultValue());}}columnEntity.setColumnName(columnName);columnList.add(columnEntity);}tableEntity.setColumnList(columnList);}
}

拼接SQL语句类(SQLBuilder) 这里说下在拼创建表的sql的时候 我并没有把字段类型拼上 这是由于对于sqllite数据库 它有个特点就是可以是无类型的 意思就是你给它什么类型 它就会存什么类型 所以我省去转化类型的步骤

//拼接插入的sql语句
public static <T> BindSQL getInsertSQL(TableEntity tableEntity,T entity){StringBuilder sql = new StringBuilder();StringBuilder valueSql = new StringBuilder();int size = tableEntity.getColumnList().size();Object[] args = new Object[size+1];sql.append("INSERT INTO ").append(tableEntity.getTableName()).append("(");valueSql.append(" VALUES(");int i = 0;PrimaryKeyEntity primaryKey = tableEntity.getPrimaryKey();if(null!=primaryKey&&!primaryKey.isAutoGenerate()){sql.append(primaryKey.getColumnName()+",");valueSql.append("?,");args[i++] = primaryKey.getValue(entity);}for (ColumnEntity columnEntity:tableEntity.getColumnList()){Object valueObj = columnEntity.getValue(entity);if(null!=valueObj){sql.append(columnEntity.getColumnName());sql.append(",");valueSql.append("?");valueSql.append(",");args[i++] = columnEntity.getValue(entity);}}sql.deleteCharAt(sql.length() - 1);valueSql.deleteCharAt(valueSql.length()-1);sql.append(")");valueSql.append(")");sql.append(valueSql);Object[] args2 = new Object[i];System.arraycopy(args,0,args2,0,i);return new BindSQL(sql.toString(),args2);};

执行数据库操作管理类(SQLExecuteManager ):

/*** 新增一条数据*/
public <T> long insert(T entity){TableEntity tableEntity = TableEntityManager.getTableEntity(entity);BindSQL bindSQL = SQLBuilder.getInsertSQL(tableEntity,entity);long rowId =  insert(bindSQL.getSql(),bindSQL.getBindArgs());return rowId;
}

框架入口类(SQLiteDB)

 /*** 新增一条数据*/public <T> long insert(T entity){return mSQLExecuteManager.insert(entity);}

整个easyDB数据库框架的大体结构就介绍到这里了,大家可以下载源码查看更多实现 ,还有很多不足的地方 比如不支持多数据库,线程安全等 也可以自行扩展。

这篇关于一起来写个SQLite ORM数据库框架(下)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1047664

相关文章

Spring Security基于数据库的ABAC属性权限模型实战开发教程

《SpringSecurity基于数据库的ABAC属性权限模型实战开发教程》:本文主要介绍SpringSecurity基于数据库的ABAC属性权限模型实战开发教程,本文给大家介绍的非常详细,对大... 目录1. 前言2. 权限决策依据RBACABAC综合对比3. 数据库表结构说明4. 实战开始5. MyBA

Ubuntu中远程连接Mysql数据库的详细图文教程

《Ubuntu中远程连接Mysql数据库的详细图文教程》Ubuntu是一个以桌面应用为主的Linux发行版操作系统,这篇文章主要为大家详细介绍了Ubuntu中远程连接Mysql数据库的详细图文教程,有... 目录1、版本2、检查有没有mysql2.1 查询是否安装了Mysql包2.2 查看Mysql版本2.

Oracle数据库常见字段类型大全以及超详细解析

《Oracle数据库常见字段类型大全以及超详细解析》在Oracle数据库中查询特定表的字段个数通常需要使用SQL语句来完成,:本文主要介绍Oracle数据库常见字段类型大全以及超详细解析,文中通过... 目录前言一、字符类型(Character)1、CHAR:定长字符数据类型2、VARCHAR2:变长字符数

Win11安装PostgreSQL数据库的两种方式详细步骤

《Win11安装PostgreSQL数据库的两种方式详细步骤》PostgreSQL是备受业界青睐的关系型数据库,尤其是在地理空间和移动领域,:本文主要介绍Win11安装PostgreSQL数据库的... 目录一、exe文件安装 (推荐)下载安装包1. 选择操作系统2. 跳转到EDB(PostgreSQL 的

SpringBoot实现数据库读写分离的3种方法小结

《SpringBoot实现数据库读写分离的3种方法小结》为了提高系统的读写性能和可用性,读写分离是一种经典的数据库架构模式,在SpringBoot应用中,有多种方式可以实现数据库读写分离,本文将介绍三... 目录一、数据库读写分离概述二、方案一:基于AbstractRoutingDataSource实现动态

C#使用SQLite进行大数据量高效处理的代码示例

《C#使用SQLite进行大数据量高效处理的代码示例》在软件开发中,高效处理大数据量是一个常见且具有挑战性的任务,SQLite因其零配置、嵌入式、跨平台的特性,成为许多开发者的首选数据库,本文将深入探... 目录前言准备工作数据实体核心技术批量插入:从乌龟到猎豹的蜕变分页查询:加载百万数据异步处理:拒绝界面

C# WinForms存储过程操作数据库的实例讲解

《C#WinForms存储过程操作数据库的实例讲解》:本文主要介绍C#WinForms存储过程操作数据库的实例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、存储过程基础二、C# 调用流程1. 数据库连接配置2. 执行存储过程(增删改)3. 查询数据三、事务处

mysql数据库重置表主键id的实现

《mysql数据库重置表主键id的实现》在我们的开发过程中,难免在做测试的时候会生成一些杂乱无章的SQL主键数据,本文主要介绍了mysql数据库重置表主键id的实现,具有一定的参考价值,感兴趣的可以了... 目录关键语法演示案例在我们的开发过程中,难免在做测试的时候会生成一些杂乱无章的SQL主键数据,当我们

Python Dash框架在数据可视化仪表板中的应用与实践记录

《PythonDash框架在数据可视化仪表板中的应用与实践记录》Python的PlotlyDash库提供了一种简便且强大的方式来构建和展示互动式数据仪表板,本篇文章将深入探讨如何使用Dash设计一... 目录python Dash框架在数据可视化仪表板中的应用与实践1. 什么是Plotly Dash?1.1

基于Flask框架添加多个AI模型的API并进行交互

《基于Flask框架添加多个AI模型的API并进行交互》:本文主要介绍如何基于Flask框架开发AI模型API管理系统,允许用户添加、删除不同AI模型的API密钥,感兴趣的可以了解下... 目录1. 概述2. 后端代码说明2.1 依赖库导入2.2 应用初始化2.3 API 存储字典2.4 路由函数2.5 应