一起来写个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基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

MySQL数据库宕机,启动不起来,教你一招搞定!

作者介绍:老苏,10余年DBA工作运维经验,擅长Oracle、MySQL、PG、Mongodb数据库运维(如安装迁移,性能优化、故障应急处理等)公众号:老苏畅谈运维欢迎关注本人公众号,更多精彩与您分享。 MySQL数据库宕机,数据页损坏问题,启动不起来,该如何排查和解决,本文将为你说明具体的排查过程。 查看MySQL error日志 查看 MySQL error日志,排查哪个表(表空间

cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个?

跨平台系列 cross-plateform 跨平台应用程序-01-概览 cross-plateform 跨平台应用程序-02-有哪些主流技术栈? cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个? cross-plateform 跨平台应用程序-04-React Native 介绍 cross-plateform 跨平台应用程序-05-Flutte

Spring框架5 - 容器的扩展功能 (ApplicationContext)

private static ApplicationContext applicationContext;static {applicationContext = new ClassPathXmlApplicationContext("bean.xml");} BeanFactory的功能扩展类ApplicationContext进行深度的分析。ApplicationConext与 BeanF

数据治理框架-ISO数据治理标准

引言 "数据治理"并不是一个新的概念,国内外有很多组织专注于数据治理理论和实践的研究。目前国际上,主要的数据治理框架有ISO数据治理标准、GDI数据治理框架、DAMA数据治理管理框架等。 ISO数据治理标准 改标准阐述了数据治理的标准、基本原则和数据治理模型,是一套完整的数据治理方法论。 ISO/IEC 38505标准的数据治理方法论的核心内容如下: 数据治理的目标:促进组织高效、合理地

深入理解数据库的 4NF:多值依赖与消除数据异常

在数据库设计中, "范式" 是一个常常被提到的重要概念。许多初学者在学习数据库设计时,经常听到第一范式(1NF)、第二范式(2NF)、第三范式(3NF)以及 BCNF(Boyce-Codd范式)。这些范式都旨在通过消除数据冗余和异常来优化数据库结构。然而,当我们谈到 4NF(第四范式)时,事情变得更加复杂。本文将带你深入了解 多值依赖 和 4NF,帮助你在数据库设计中消除更高级别的异常。 什么是

ZooKeeper 中的 Curator 框架解析

Apache ZooKeeper 是一个为分布式应用提供一致性服务的软件。它提供了诸如配置管理、分布式同步、组服务等功能。在使用 ZooKeeper 时,Curator 是一个非常流行的客户端库,它简化了 ZooKeeper 的使用,提供了高级的抽象和丰富的工具。本文将详细介绍 Curator 框架,包括它的设计哲学、核心组件以及如何使用 Curator 来简化 ZooKeeper 的操作。 1

DM8数据库安装后配置

1 前言 在上篇文章中,我们已经成功将库装好。在安装完成后,为了能够更好地满足应用需求和保障系统的安全稳定运行,通常需要进行一些基本的配置。下面是一些常见的配置项: 数据库服务注册:默认包含14个功能模块,将这些模块注册成服务后,可以更好的启动和管理这些功能;基本的实例参数配置:契合应用场景和发挥系统的最大性能;备份:有备无患;… 2 注册实例服务 注册了实例服务后,可以使用系统服务管理,

【Kubernetes】K8s 的安全框架和用户认证

K8s 的安全框架和用户认证 1.Kubernetes 的安全框架1.1 认证:Authentication1.2 鉴权:Authorization1.3 准入控制:Admission Control 2.Kubernetes 的用户认证2.1 Kubernetes 的用户认证方式2.2 配置 Kubernetes 集群使用密码认证 Kubernetes 作为一个分布式的虚拟

速了解MySQL 数据库不同存储引擎

快速了解MySQL 数据库不同存储引擎 MySQL 提供了多种存储引擎,每种存储引擎都有其特定的特性和适用场景。了解这些存储引擎的特性,有助于在设计数据库时做出合理的选择。以下是 MySQL 中几种常用存储引擎的详细介绍。 1. InnoDB 特点: 事务支持:InnoDB 是一个支持 ACID(原子性、一致性、隔离性、持久性)事务的存储引擎。行级锁:使用行级锁来提高并发性,减少锁竞争