一起来写个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

相关文章

Linux下MySQL数据库定时备份脚本与Crontab配置教学

《Linux下MySQL数据库定时备份脚本与Crontab配置教学》在生产环境中,数据库是核心资产之一,定期备份数据库可以有效防止意外数据丢失,本文将分享一份MySQL定时备份脚本,并讲解如何通过cr... 目录备份脚本详解脚本功能说明授权与可执行权限使用 Crontab 定时执行编辑 Crontab添加定

如何通过try-catch判断数据库唯一键字段是否重复

《如何通过try-catch判断数据库唯一键字段是否重复》在MyBatis+MySQL中,通过try-catch捕获唯一约束异常可避免重复数据查询,优点是减少数据库交互、提升并发安全,缺点是异常处理开... 目录1、原理2、怎么理解“异常走的是数据库错误路径,开销比普通逻辑分支稍高”?1. 普通逻辑分支 v

GSON框架下将百度天气JSON数据转JavaBean

《GSON框架下将百度天气JSON数据转JavaBean》这篇文章主要为大家详细介绍了如何在GSON框架下实现将百度天气JSON数据转JavaBean,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录前言一、百度天气jsON1、请求参数2、返回参数3、属性映射二、GSON属性映射实战1、类对象映

Python与MySQL实现数据库实时同步的详细步骤

《Python与MySQL实现数据库实时同步的详细步骤》在日常开发中,数据同步是一项常见的需求,本篇文章将使用Python和MySQL来实现数据库实时同步,我们将围绕数据变更捕获、数据处理和数据写入这... 目录前言摘要概述:数据同步方案1. 基本思路2. mysql Binlog 简介实现步骤与代码示例1

Python ORM神器之SQLAlchemy基本使用完全指南

《PythonORM神器之SQLAlchemy基本使用完全指南》SQLAlchemy是Python主流ORM框架,通过对象化方式简化数据库操作,支持多数据库,提供引擎、会话、模型等核心组件,实现事务... 目录一、什么是SQLAlchemy?二、安装SQLAlchemy三、核心概念1. Engine(引擎)

使用shardingsphere实现mysql数据库分片方式

《使用shardingsphere实现mysql数据库分片方式》本文介绍如何使用ShardingSphere-JDBC在SpringBoot中实现MySQL水平分库,涵盖分片策略、路由算法及零侵入配置... 目录一、ShardingSphere 简介1.1 对比1.2 核心概念1.3 Sharding-Sp

Go语言连接MySQL数据库执行基本的增删改查

《Go语言连接MySQL数据库执行基本的增删改查》在后端开发中,MySQL是最常用的关系型数据库之一,本文主要为大家详细介绍了如何使用Go连接MySQL数据库并执行基本的增删改查吧... 目录Go语言连接mysql数据库准备工作安装 MySQL 驱动代码实现运行结果注意事项Go语言执行基本的增删改查准备工作

MySQL 数据库表操作完全指南:创建、读取、更新与删除实战

《MySQL数据库表操作完全指南:创建、读取、更新与删除实战》本文系统讲解MySQL表的增删查改(CURD)操作,涵盖创建、更新、查询、删除及插入查询结果,也是贯穿各类项目开发全流程的基础数据交互原... 目录mysql系列前言一、Create(创建)并插入数据1.1 单行数据 + 全列插入1.2 多行数据

MySQL 数据库表与查询操作实战案例

《MySQL数据库表与查询操作实战案例》本文将通过实际案例,详细介绍MySQL中数据库表的设计、数据插入以及常用的查询操作,帮助初学者快速上手,感兴趣的朋友跟随小编一起看看吧... 目录mysql 数据库表操作与查询实战案例项目一:产品相关数据库设计与创建一、数据库及表结构设计二、数据库与表的创建项目二:员

MybatisPlus中removeById删除数据库未变解决方案

《MybatisPlus中removeById删除数据库未变解决方案》MyBatisPlus中,removeById需实体类标注@TableId注解以识别数据库主键,若字段名不一致,应通过value属... 目录MyBATisPlus中removeBypythonId删除数据库未变removeById(Se