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

相关文章

Python调用Orator ORM进行数据库操作

《Python调用OratorORM进行数据库操作》OratorORM是一个功能丰富且灵活的PythonORM库,旨在简化数据库操作,它支持多种数据库并提供了简洁且直观的API,下面我们就... 目录Orator ORM 主要特点安装使用示例总结Orator ORM 是一个功能丰富且灵活的 python O

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景

使用Navicat工具比对两个数据库所有表结构的差异案例详解

《使用Navicat工具比对两个数据库所有表结构的差异案例详解》:本文主要介绍如何使用Navicat工具对比两个数据库test_old和test_new,并生成相应的DDLSQL语句,以便将te... 目录概要案例一、如图两个数据库test_old和test_new进行比较:二、开始比较总结概要公司存在多

MySQL数据库函数之JSON_EXTRACT示例代码

《MySQL数据库函数之JSON_EXTRACT示例代码》:本文主要介绍MySQL数据库函数之JSON_EXTRACT的相关资料,JSON_EXTRACT()函数用于从JSON文档中提取值,支持对... 目录前言基本语法路径表达式示例示例 1: 提取简单值示例 2: 提取嵌套值示例 3: 提取数组中的值注意

修改若依框架Token的过期时间问题

《修改若依框架Token的过期时间问题》本文介绍了如何修改若依框架中Token的过期时间,通过修改`application.yml`文件中的配置来实现,默认单位为分钟,希望此经验对大家有所帮助,也欢迎... 目录修改若依框架Token的过期时间修改Token的过期时间关闭Token的过期时js间总结修改若依

查询SQL Server数据库服务器IP地址的多种有效方法

《查询SQLServer数据库服务器IP地址的多种有效方法》作为数据库管理员或开发人员,了解如何查询SQLServer数据库服务器的IP地址是一项重要技能,本文将介绍几种简单而有效的方法,帮助你轻松... 目录使用T-SQL查询方法1:使用系统函数方法2:使用系统视图使用SQL Server Configu

SQL Server数据库迁移到MySQL的完整指南

《SQLServer数据库迁移到MySQL的完整指南》在企业应用开发中,数据库迁移是一个常见的需求,随着业务的发展,企业可能会从SQLServer转向MySQL,原因可能是成本、性能、跨平台兼容性等... 目录一、迁移前的准备工作1.1 确定迁移范围1.2 评估兼容性1.3 备份数据二、迁移工具的选择2.1

Python中连接不同数据库的方法总结

《Python中连接不同数据库的方法总结》在数据驱动的现代应用开发中,Python凭借其丰富的库和强大的生态系统,成为连接各种数据库的理想编程语言,下面我们就来看看如何使用Python实现连接常用的几... 目录一、连接mysql数据库二、连接PostgreSQL数据库三、连接SQLite数据库四、连接Mo

Oracle数据库如何切换登录用户(system和sys)

《Oracle数据库如何切换登录用户(system和sys)》文章介绍了如何使用SQL*Plus工具登录Oracle数据库的system用户,包括打开登录入口、输入用户名和口令、以及切换到sys用户的... 目录打开登录入口登录system用户总结打开登录入口win+R打开运行对话框,输php入:sqlp

数据库使用之union、union all、各种join的用法区别解析

《数据库使用之union、unionall、各种join的用法区别解析》:本文主要介绍SQL中的Union和UnionAll的区别,包括去重与否以及使用时的注意事项,还详细解释了Join关键字,... 目录一、Union 和Union All1、区别:2、注意点:3、具体举例二、Join关键字的区别&php