面向对象式手写数据库架构
来源:互联网 发布:设计模式 java最常用 编辑:程序博客网 时间:2024/06/05 16:38
android中使用sqlite作为数据库存储数据,操作数据库最常见的是继承SqliteOpenHelper实现数据库表的操作,网上也有很多框架比如litepal,GreenDao等等。
现在我们自己实现类似的数据库框架
大致框架图
主要用到泛型、反射、注解。
编写注解DbTable,获取实体类名上的表名
package com.tony.dbdemo.db.annotion;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * Created by Tony on 2017/6/4. *///TYPE:用在类名上@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)public @interface DbTable { String value();}
编写注解DbField,获取实体类字段上的表的列名
package com.tony.dbdemo.db.annotion;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * Created by Tony on 2017/6/4. */@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface DbField { String value();}
编写实体类User
字段不能为private修饰,否则反射Class.getFields()拿不到字段
import com.tony.dbdemo.db.annotion.DbTable;/** * Created by Tony on 2017/6/4. */@DbTable("tb_user")public class User { @DbField("name") public String name; @DbField("password") public String password; public User(String name,String password){ this.name = name; this.password = password; } public User(){ }}
定义接口IBaseDao.java
package com.tony.dbdemo.db;import java.util.List;/** * Created by Tony on 2017/6/4. */public interface IBaseDao<T> { /** * 插入对象到数据库 * @param entity * @return */ Long insert(T entity); /** * 修改数据 * @param entity * @param where * @return */ int update(T entity,T where); /** * 删除数据 * @param where * @return */ int delete(T where); /** * 查询数据 */ List<T> query(T where); List<T> query(T where,String orderBy,Integer startIndex,Integer limit);}
定义实现IBaseDao的类BaseDao.java
package com.tony.dbdemo.db;import android.content.ContentValues;import android.database.Cursor;import android.database.sqlite.SQLiteDatabase;import android.text.TextUtils;import com.tony.dbdemo.db.annotion.DbField;import com.tony.dbdemo.db.annotion.DbTable;import java.lang.reflect.Field;import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.Set;/** * Created by Administrator on 2017/1/9 0009. */public abstract class BaseDao<T> implements IBaseDao<T> { /**] * 持有数据库操作类的引用 */ private SQLiteDatabase database; /** * 保证实例化一次 */ private boolean isInit=false; /** * 持有操作数据库表所对应的java类型 * User */ private Class<T> entityClass; /** * 维护这表名与成员变量名的映射关系 * key---》表名 * value --》Field */ private HashMap<String,Field> cacheMap; private String tableName; /** * @param entity * @param sqLiteDatabase * @return * 实例化一次 */ protected synchronized boolean init(Class<T> entity, SQLiteDatabase sqLiteDatabase) { if(!isInit) { entityClass=entity; database=sqLiteDatabase; if (entity.getAnnotation(DbTable.class)==null) { tableName=entity.getClass().getSimpleName(); }else { tableName=entity.getAnnotation(DbTable.class).value(); } if(!database.isOpen()) { return false; } if(!TextUtils.isEmpty(createTable())) { database.execSQL(createTable()); } cacheMap=new HashMap<>(); initCacheMap(); isInit=true; } return isInit; } /** * 维护映射关系 */ private void initCacheMap() { String sql="select * from "+this.tableName+" limit 1 , 0"; Cursor cursor=null; try { cursor=database.rawQuery(sql,null); /** * 表的列名数组 */ String[] columnNames=cursor.getColumnNames(); /** * 拿到Filed数组 */ Field[] colmunFields=entityClass.getFields(); for(Field filed:colmunFields) { filed.setAccessible(true); } /** * 开始找对应关系 */ for(String colmunName:columnNames) { /** * 如果找到对应的Filed就赋值给他 * User */ Field colmunFiled=null; for (Field field:colmunFields) { String fieldName=null; if(field.getAnnotation(DbField.class)!=null) { fieldName=field.getAnnotation(DbField.class).value(); }else { fieldName =field.getName(); } /** * 如果表的列名 等于了 成员变量的注解名字 */ if(colmunName.equals(fieldName)) { colmunFiled= field; break; } } //找到了对应关系 if(colmunFiled!=null) { cacheMap.put(colmunName,colmunFiled); } } }catch (Exception e) { }finally { cursor.close(); } } @Override public Long insert(T entity) { Map<String,String> map=getValues(entity); ContentValues values=getContentValues(map); Long result =database.insert(tableName,null,values); return result; } /** * 讲map 转换成ContentValues * @param map * @return */ private ContentValues getContentValues(Map<String, String> map) { ContentValues contentValues=new ContentValues(); Set keys=map.keySet(); Iterator<String> iterator=keys.iterator(); while (iterator.hasNext()) { String key=iterator.next(); String value=map.get(key); if(value!=null) { contentValues.put(key,value); } } return contentValues; } /** * 创建表 * @return */ protected abstract String createTable(); private Map<String, String> getValues(T entity) { HashMap<String,String> result=new HashMap<>(); Iterator<Field> filedsIterator=cacheMap.values().iterator(); /** * 循环遍历 映射map的 Filed */ while (filedsIterator.hasNext()) { /** * */ Field colmunToFiled=filedsIterator.next(); String cacheKey=null; String cacheValue=null; if(colmunToFiled.getAnnotation(DbField.class)!=null) { cacheKey=colmunToFiled.getAnnotation(DbField.class).value(); }else { cacheKey=colmunToFiled.getName(); } try { if(null==colmunToFiled.get(entity)) { continue; } cacheValue=colmunToFiled.get(entity).toString(); } catch (IllegalAccessException e) { e.printStackTrace(); } result.put(cacheKey,cacheValue); } return result; } @Override public int update(T entity, T where) { int result = -1; Map values = getValues(entity); /** * 将条件对象 转换map */ Map whereClause = getValues(where); Condition condition = new Condition(whereClause); ContentValues contentValues = getContentValues(values); result = database.update(tableName,contentValues,condition.getWhereClause(),condition.getWhereArgs()); return result; } @Override public int delete(T where) { Map map = getValues(where); Condition condition = new Condition(map); int result = database.delete(tableName,condition.getWhereClause(),condition.getWhereArgs()); return result; } @Override public List<T> query(T where) { return query(where,null,null,null); } @Override public List<T> query(T where, String orderBy, Integer startIndex, Integer limit) { Map map = getValues(where); String limitString = null; if (startIndex != null && limit != null){ limitString = startIndex+" , "+limit; } Condition condition = new Condition(map); Cursor cursor = database.query(tableName,null,condition.getWhereClause(),condition.getWhereArgs(),null,null,orderBy,limitString); List<T> result = getResult(cursor,where); cursor.close(); return result; } private List<T> getResult(Cursor cursor, T where) { ArrayList list = new ArrayList(); Object item; while (cursor.moveToNext()) { try { item = where.getClass().newInstance(); /** * 列名 name * 成员变量 Field */ Iterator iterator = cacheMap.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry entry = (Map.Entry) iterator.next(); /** * 得到列名 */ String columnName = (String) entry.getKey(); /** * 然后以列名拿到 列名在游标的位置 */ Integer columnIndex = cursor.getColumnIndex(columnName); Field field = (Field) entry.getValue(); Class type = field.getType(); if (columnIndex!=-1){ if (type == String.class) { //反射方式赋值 field.set(item,cursor.getString(columnIndex)); }else if (type == Double.class){ field.set(item,cursor.getDouble(columnIndex)); }else if (type == Integer.class){ field.set(item,cursor.getInt(columnIndex)); }else if (type == Long.class){ field.set(item,cursor.getLong(columnIndex)); }else if (type == byte[].class){ field.set(item,cursor.getBlob(columnIndex)); }else { /** * 不支持的类型 */ continue; } } } list.add(item); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } return list; } /** * 封装修改语句 */ class Condition { /** * 查询条件 * name=?&&password=? */ private String whereClause; /** * 参数 */ private String[] whereArgs; public Condition(Map<String,String> whereClause) { ArrayList list = new ArrayList(); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append(" 1=1 "); Set keys = whereClause.keySet(); Iterator iterator = keys.iterator(); while (iterator.hasNext()){ String key = (String) iterator.next(); String value = whereClause.get(key); if (value!=null){ /** * 拼接条件查询语句 */ stringBuilder.append(" and "+key+" =?"); list.add(value); } } this.whereClause = stringBuilder.toString(); //list转化为你所需要类型的数组 this.whereArgs = (String[]) list.toArray(new String[list.size()]); } public String getWhereClause() { return whereClause; public void setWhereClause(String whereClause) { this.whereClause = whereClause; } public String[] getWhereArgs() { return whereArgs; } public void setWhereArgs(String[] whereArgs) { this.whereArgs = whereArgs; } }}
定义BaseDaoFactory初始化BaseDao
package com.tony.dbdemo.db;import android.database.sqlite.SQLiteDatabase;import android.os.Environment;/** * Created by Tony on 2017/6/4. */public class BaseDaoFactory { private String sqliteDatabasePath; private SQLiteDatabase sqLiteDatabase; private static BaseDaoFactory Instence = new BaseDaoFactory(); public static BaseDaoFactory getInstence(){ return Instence; } public BaseDaoFactory(){ sqliteDatabasePath = Environment.getExternalStorageDirectory().getAbsolutePath()+"/teacher.db"; openDatabase(); } private void openDatabase() { this.sqLiteDatabase = SQLiteDatabase.openOrCreateDatabase(sqliteDatabasePath,null); } public synchronized <T extends BaseDao<M>,M> T getDataHelper(Class<T> clazz, Cass<M> entityClass){ BaseDao baseDao = null; try { baseDao = clazz.newInstance(); baseDao.init(entityClass,sqLiteDatabase); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return (T) baseDao; }}
MainActivity测试
package com.tony.dbdemo;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import android.view.View;import com.tony.dbdemo.Bean.File;import com.tony.dbdemo.Bean.User;import com.tony.dbdemo.Dao.FileDao;import com.tony.dbdemo.Dao.UserDao;import com.tony.dbdemo.db.BaseDaoFactory;import com.tony.dbdemo.db.IBaseDao;import java.util.List;public class MainActivity extends AppCompatActivity { IBaseDao<User> baseDao; IBaseDao<File> fileDao; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); baseDao = BaseDaoFactory.getInstence().getDataHelper(UserDao.class,User.class); //fileDao = BaseDaoFactory.getInstence().getDataHelper(FileDao.class,File.class); } public void save(View v){ for (int i = 0; i < 10; i++) { User user = new User(i+1,"Tony"+i,"123456"); baseDao.insert(user); } /*File file = new File("2017-6-5","data/data/path","插入文件操作记录"); fileDao.insert(file);*/ } public void update(View v){ User where = new User(); where.userId=1; User user = new User(2,"David","123456789"); baseDao.update(user,where); } public void delete(View v){ User user = new User(); user.name="David"; baseDao.delete(user); } public void query(View v){ User where = new User(); where.name="David"; where.userId=1; List<User> list = baseDao.query(where); Log.i(MainActivity.class.getName(),"查询到 "+list.size()+" 条数据"); for (User user : list){ Log.i(MainActivity.class.getName(),user.toString()); } }}
布局文件
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.tony.dbdemo.MainActivity"> <Button android:layout_width="246dp" android:layout_height="45dp" android:text="save" android:onClick="save" android:layout_gravity="center" /> <Button android:layout_width="246dp" android:layout_height="43dp" android:text="update" android:onClick="update" android:layout_gravity="center" /> <Button android:layout_width="246dp" android:layout_height="43dp" android:text="delete" android:onClick="delete" android:layout_gravity="center" /> <Button android:layout_width="246dp" android:layout_height="43dp" android:text="query" android:onClick="query" android:layout_gravity="center" /></LinearLayout>
源码地址:https://github.com/fsdsds/DBDemo
阅读全文
0 0
- 面向对象式手写数据库架构
- 面向对象式手写数据库框架
- 移动架构29_面向对象式手写数据库架构设计一(基本框架与插入数据)
- 移动架构30_面向对象式手写数据库架构设计二(修改、删除、查询、拓展)
- 架构;面向对象
- 1.面向对象数据库
- 面向对象数据库
- 面向对象和数据库
- 数据库面向对象设计
- 面向对象数据库
- 面向对象数据库
- 面向对象架构 设计原则
- 面向对象的架构设计
- 系统架构之面向对象
- DB4o面向对象数据库介绍
- 面向对象技术和数据库
- LINQ面向对象数据库编程
- 面向对象技术和数据库
- 程序员的工作、学习与绩效
- Kotlin 从学习到 Android 第六章 类和继承
- 一步搭建phpwind网站
- 正则表达式_五大方法
- 记一个可以打开,关闭的log日志
- 面向对象式手写数据库架构
- 线段树详解 (原理,实现与应用)
- 【阿里云服务器】外网无法访问tomcat下部署的项目
- Android悬浮通知无效的问题
- 在主方法中创建String型变量,并判断变量的前导和后置字符串
- [基础常识]一步搭建phpwind网站
- 编写一个search(s)的函数,将当前目录及其所有子目录下查找文件名包含指定字符串的文件,打印完整路径
- MYSQL如何设置大小写敏感
- 在objective-c中导入Swift,"工程名-Swift.h" 文件找不到