本专栏专注分享大型Bat面试知识,后续会持续更新,喜欢的话麻烦点击一个关注

面试官: 你曾经有没有对SqliteDatabase做过封装,你自己有设计过数据库框架吗?或者只是停留在使用ormlite greenDao这类框架

心理分析:面试官比较在架构方面的知识,特别是数据库的,大多数开发者 并不理解为什么能够直接拿来用的,腾讯反而要求你自己写。其实小公司大多是拿来主义。而大公司不一样,需要考虑的需求和变化都比较多。所以当问到有没有做过数据框架的时候,很多人直接说 我使用过。这并不能成为你录取你的理由

**求职者:**应该从 为什么sqlitedatabase这种api死板,不能服用,容易出错开始讲起。再到整体数据库架构设计的角度出发,一步一步告诉面试官你是如何实现数据库框架

数据库在某些特定需求下是很重要的,像持久化数据,一些不需要实时或者长时间不变的数据,可以放在数据库中做缓存,这样就算用户网络不好或者断网的情况下,依然是可以查看一些以前的数据。像新闻或者咨询类。这样做是不可避免的。提高用户的体验。

谷歌为我们开发者提供了最基础的数据库操作类,同时也提供了SqliteDatabase直接创建修改数据库和表

但是只是这样不能满足我们平时的敏捷开发
作为一个应用层程序员,很多时候只是想去关心存储和读取数据,数据处理等问题的解决。

而不是花时间和精力在如何去存,如何去取数据库数据。这就是架构出现的前提。将一些面向过程的算法或者业务逻辑封装,可再次调用。易扩展、高灵敏。让程序猿专心的去整理项目需求和逻辑。解放大脑,提高工作效率。

现在数据库有很多三方框架,比如GreenDao,Afinal、xUtils、ThinkAndroid、volley等等。

但是这些三方导入后,文件数太大了。而且很多都集成了网络加载框架,图片加载框架。

这样就有了一定的耦合性。比如我只喜欢xUtils的数据库框架,不喜欢它的网络加载,想用Volley的网络加载框架。

咋办呢?两个都导入?是的,可以这样,但是项目的文件数就太大了。编译时压力大。而且一些公司想让程序猿写自己的框架,不使用别人发布的框架,这样代码是可以高扩展的。出现什么问题也是可以及时修改。如果导入的三方库在项目成熟阶段出现问题。那是不是要推翻这个库,重新去导入一个,重新在写一遍逻辑,而且又有谁能保证,再次导入的库不会出错呢?

我把大致的封装思路,以图片的形式展示出来。

对应的UML图

使用起来也非常方便,这里的映射逻辑和GreenDao的底层源码使用的是一个原理。采用表和类属性映射,并对其进行了缓存。只有在切换表的链接时,会重新建立链接。

优点:

1、支持sql语句自拼接。数据库直接执行sql语句。

2、支持传入类对象进行增删改查,比如User,在insert的时候,插入User的实例,属性都封装在user中。通过反射获取它的属性值,存入数据库。

3、高扩展,每个新建的存储类型。直接继承DefaultBaseDao即可。可以在这里做一些该类独有的操作。

4、支持多数据库切换,多数据库操作。同时支持数据库分库管理,多数据库多版本多用户同时升级,采取XML脚本升级。这里的脚本语句没有封装。

5、支持boolean、byte、short、int、long、float、double数据类型的存储和读取。

使用注意事项:

1、创建存储数据类时,需要使用注解去标注类名(表名@DbTable)、类属性(表字段@DbField)。若是有主键(@DbPrimaryField)也需要标注。

2、需要创建一个相应的Dao层类和数据库的链接。

使用时导入gandle: compile ‘com.singleshu8:LemonDao:1.0.4’

创建一个Dao层,这里可以操作数据库,像多数据升级时,这里可以做一些特定处理。对外扩展

public class FileDao extends DefaultBaseDao {
}
@DbTable(value = "tb_file")
public class FileModel {@DbPrimaryField(value = "id")private int id;@DbField(value = "tb_filename")private String fileName;@DbField(value = "tb_filepath")private String filePath;@DbField(value = "tb_fileid")private int fileId;public String getFileName() {return fileName;}public void setFileName(String fileName) {this.fileName = fileName;}public String getFilePath() {return filePath;}public void setFilePath(String filePath) {this.filePath = filePath;}public int getFileId() {return fileId;}public void setFileId(int fileId) {this.fileId = fileId;}
}
@DbTable(value = "tb_user")
public class User {@DbPrimaryField(value = "id")private Integer id;@DbField(value = "user_name")private String name;@DbField(value = "user_address")private String address;@DbField(value = "user_psw")private String psw;@DbField(value = "user_status")private Integer status;@DbField(value = "user_id")private String user_id;@DbField(value = "isMe")private Boolean isMe;@DbField(value = "myAge")private Double myAge;@DbField(value = "myPhone")private Long myPhone;@DbField(value = "aShort")private Short aShort;public User(String name, String address, String psw, Integer status, String user_id, Boolean isMe, Double myAge, Long myPhone, Short aShort) {this.name = name;this.address = address;this.psw = psw;this.status = status;this.user_id = user_id;this.isMe = isMe;this.myAge = myAge;this.myPhone = myPhone;this.aShort = aShort;}public User() {}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}public String getPsw() {return psw;}public void setPsw(String psw) {this.psw = psw;}public Integer getStatus() {return status;}public void setStatus(Integer status) {this.status = status;}public String getUser_id() {return user_id;}public void setUser_id(String user_id) {this.user_id = user_id;}public Boolean getMe() {return isMe;}public void setMe(Boolean me) {isMe = me;}public Double getMyAge() {return myAge;}public void setMyAge(Double myAge) {this.myAge = myAge;}public Long getMyPhone() {return myPhone;}public void setMyPhone(Long myPhone) {this.myPhone = myPhone;}public Short getaShort() {return aShort;}public void setaShort(Short aShort) {this.aShort = aShort;}@Overridepublic String toString() {return "User{" +"id=" + id +", name='" + name + '\'' +", address='" + address + '\'' +", psw='" + psw + '\'' +", status=" + status +", user_id='" + user_id + '\'' +", isMe=" + isMe +", myAge=" + myAge +", myPhone=" + myPhone +", aShort=" + aShort +'}';}
}
public class UserDao extends DefaultBaseDao<User> {//    @Override
//    public Long insert(User entity) {
//        List<User> list=query(new User());
//        User where = null;
//        for (User user:list)
//        {
//            where =new User();
//            where.setUser_id(user.getUser_id());
//            user.setStatus(0);
//            Log.i(TAG,"用户"+user.getName()+"更改为未登录状态");
//            update(user,where);
//        }
//        Log.i(TAG,"用户"+entity.getName()+"登录");
//        entity.setStatus(1);
//        return super.insert(entity);
//    }/*** 得到当前登录的User* @return*/public User getCurrentUser() {User user=new User();user.setStatus(1);List<User> list=query(user);if(list.size()>0){return list.get(0);}return null;}
}
具体使用
public class MainActivity extends AppCompatActivity {private IBaseDao iBaseDao;String dbFile;int i = 0;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//数据库地址  文件夹dbFile = Environment.getExternalStorageDirectory().getAbsolutePath() + "/myDb";//6.0以上动态申请权限PermissionUtils.getInstance().requestPermission(this);}public void click(View view){switch (view.getId()){//myselft.db数据库 添加用户case R.id.add_user://建立数据库和表的链接iBaseDao = BaseDaoFactory.getInstance().getSqliteComponent(UserDao.class,User.class,dbFile,"myselft.db");//iBaseDao.insert("insert into tb_user(user_name,user_address,user_psw,user_status,user_id,isMe,myAge,myPhone,aShort) values('鬼刀','六极之地','123456',1,'user_90','true',1.234,457864745,1234)");//可以使用对象进行封装存入//可以使用sql语句进行存储Short si = 123;User user = new User("鬼刀","六极之地","123456",0,"user_"+i,true,1.234,457864745l,si);iBaseDao.insert(user);i++;break;case R.id.add_file://当需要切换表存储的时候,需要重新建立链接iBaseDao = BaseDaoFactory.getInstance().getSqliteComponent(FileDao.class,FileModel.class,dbFile,"myselft.db");FileModel fileModel = new FileModel();fileModel.setFilePath("d/as:/");fileModel.setFileName("qq.apk");fileModel.setFileId(123);iBaseDao.insert(fileModel);break;case R.id.add_sqlite_file://当需要切换表存储的时候,需要重新建立链接iBaseDao = BaseDaoFactory.getInstance().getSqliteComponent(FileDao.class,FileModel.class,dbFile,"mydownfile.db");FileModel fileModel1 = new FileModel();fileModel1.setFilePath("d/as:/");fileModel1.setFileName("qq.apk");fileModel1.setFileId(123);iBaseDao.insert(fileModel1);break;//删除用户case R.id.delete_user://建立数据库和表的链接iBaseDao = BaseDaoFactory.getInstance().getSqliteComponent(UserDao.class,User.class,dbFile,"myselft.db");//使用类对象进行封装删除条件//User user2 = new User();//user2.setUser_id("user_0");//由于手机数据库无法存放布尔值,在寻找条件时,必须对布尔值进行赋值。否则默认是false!//user2.setMe(true);//iBaseDao.delete(user2);//直接使用sql语句删除//iBaseDao.delete("delete from tb_user where user_id = 'user_0'");//或者使用数组封装条件iBaseDao.delete("delete from tb_user where user_id = ?",new String[]{"user_0"});break;//查询用户case R.id.query_user://建立数据库和表的链接iBaseDao = BaseDaoFactory.getInstance().getSqliteComponent(UserDao.class,User.class,dbFile,"myselft.db");User user1 = new User();user1.setName("鬼刀");//由于手机数据库无法存放布尔值,在寻找条件时,必须对布尔值进行赋值。否则默认是false!
//                user1.setMe(true);//也可以直接查询  当前条件List<User> users = iBaseDao.query(user1);//可使用表字段来规定排序//List<User> users = iBaseDao.query(user1,"user_id",0,10);//使用字符串qsl查询//List<User>users = iBaseDao.query("select * from tb_user where user_name = '鬼刀'",User.class);// 可以用数组装条件
//                List<User>users = iBaseDao.query("select * from tb_user where user_name = ?",User.class,new String[]{"鬼刀"});for (User user3:users) {Log.i("tag00",user3.toString());Log.i("tag00","================================");}break;//更新用户case R.id.update_user://建立数据库和表的链接  若是表没有换,那么就不用建立新的链接iBaseDao = BaseDaoFactory.getInstance().getSqliteComponent(UserDao.class,User.class,dbFile,"myselft.db");//更新数据  使用对象进行封装 建议使用这种 非常方便,当然有特殊的需求,就是用sql语句拼接User newUser = new User();newUser.setName("天南之剑");User where = new User();where.setMe(true);where.setUser_id("user_1");iBaseDao.update(newUser,where);//用sql语句进行更新//iBaseDao.update("update tb_user set user_name = '血天使-奥斯丁' where user_name = '天南之剑'");//用数组存放条件语句
//                iBaseDao.update("update tb_user  user_name = '天南之剑' where user_name = '血天使-奥斯丁'");break;}}@Overrideprotected void onDestroy() {super.onDestroy();//最后关闭数据库,避免内存泄露iBaseDao.close();}
}

有关于数据库分库和多版本多用户脚本升级,这个在小项目用的很少。小项目一般是几张表就搞定了。查询是加个userId,但是当 数据量过大时,这样做会很难受。数据库升级在表少的时候,可以直接拼接字符串。但是当表多了之后,这样做无疑是不正确的。

若是对数据库分库和多版本多用户升级感兴趣的朋友。可以联系我点击关于我 , 非常希望和大家一起交流 , 共同进步

觉得有用的朋友请给个关注,谢谢

自己设计过App的数据库框架?还是只是停留在使用ormlite greenDao这类框架,一篇文章帮你解答相关推荐

  1. android适配布局,大佬手把手教你如何仿写出大厂的APP,一篇文章帮你解答

    前言 程序员,近年来十分火爆的职业,凭着巨大的市场缺口和高额的薪水吸引着大量毕业生加入程序员的队伍.这其中就包括各类专业的学生,像我这种自动化专业的也在其内.这些不是计算机科班出身的可以看作是半路出家 ...

  2. java计算机毕业设计高原特色农产品网站设计源码+mysql数据库+系统+lw文档+部署

    java计算机毕业设计高原特色农产品网站设计源码+mysql数据库+系统+lw文档+部署 java计算机毕业设计高原特色农产品网站设计源码+mysql数据库+系统+lw文档+部署 本源码技术栈: 项目 ...

  3. 怎么设计一个好的数据库

    我有一个无比可恶的同窗,问了我一个非常好的问题,怎么样设计一个好的数据库,依据她这个问题,我愁闷了非常钟,而后在网上找到了下面的货色,有什么看法大家可以提出来,实在这个也是异常值得咱们程序员学习的.三 ...

  4. Java计算机毕业设计体育网站前端设计源码+系统+数据库+lw文档

    Java计算机毕业设计体育网站前端设计源码+系统+数据库+lw文档 Java计算机毕业设计体育网站前端设计源码+系统+数据库+lw文档 本源码技术栈: 项目架构:B/S架构 开发语言:Java语言 开 ...

  5. iOS App开发那些事:如何选择合适的人、规范和框架?

    话大道理,笑话小说,小白兔的笑话,小学生笑话大全,开心小笑话,小学生幽默笑话,小明系列冷笑话,小白兔笑话,笑话小故事,小明冷笑话大全,经典小笑话 合适的人 首 先明确一点,合适的人是指纯技术团队的建设 ...

  6. java计算机毕业设计线上投保的设计源码+系统+数据库+lw文档+mybatis+运行部署

    java计算机毕业设计线上投保的设计源码+系统+数据库+lw文档+mybatis+运行部署 java计算机毕业设计线上投保的设计源码+系统+数据库+lw文档+mybatis+运行部署 本源码技术栈: ...

  7. 必做作业三:基于墨刀的原型设计——词典APP

    必做作业三:基于墨刀的原型设计--词典APP 运行环境:IOS系统 作品运行地址:https://modao.cc/app/JmnRng02vm8mJDB1NmdswodOndgMHwJ 注:使用ch ...

  8. java计算机毕业设计企业进销管理系统的设计与实现源代码+数据库+系统+lw文档

    java计算机毕业设计企业进销管理系统的设计与实现源代码+数据库+系统+lw文档 java计算机毕业设计企业进销管理系统的设计与实现源代码+数据库+系统+lw文档 本源码技术栈: 项目架构:B/S架构 ...

  9. java计算机毕业设计旅游网站设计源码+系统+数据库+lw文档+mybatis+运行部署

    java计算机毕业设计旅游网站设计源码+系统+数据库+lw文档+mybatis+运行部署 java计算机毕业设计旅游网站设计源码+系统+数据库+lw文档+mybatis+运行部署 本源码技术栈: 项目 ...

  10. 怎样设计一个好的数据库

    数据库设计(Database Design)是指对于一个给定的应用环境,构造最优的数据库模式,建立数据库及其应用系统,使之能够有效地存储数据,满足各种用户的应用需求(信息要求和处理要求). 在数据库领 ...

最新文章

  1. ROS的工作模式和ESXI网卡工作模式的关系
  2. C语言课程设计选哪个,C语言课程设计选题及要求.docx
  3. 交易性金融资产账务处理问题及改进
  4. 22行代码AC_Prime Number Aizu - 0009(素数筛)(解题报告)
  5. 解决SwipeRefreshLayout与Banner滑动冲突
  6. iOS10 权限访问崩溃
  7. 微信小程序 request请求封装
  8. leetcode1471. 数组中的 k 个最强值(排序)
  9. javax.script.ScriptException: ReferenceError: xxx is not defined in eval
  10. lisp 读取样条曲线座标点_如何在lisp中求一条直线和一条曲线的交点
  11. 卡巴斯基发现新型恶意软件StoneDrill,或与 Shamoon有关
  12. c++ 删除二叉树的子树_数据结构—树|二叉树|前序遍历、中序遍历、后序遍历【图解实现】...
  13. Oracle IMP数据时报20001错误
  14. 锁屏面试题百日百刷-CSS篇(一)
  15. 在Fedora 14 alpha 下测试Kvm情况(视频)
  16. Python3 ORM hacking
  17. 从零实现深度学习框架——理解广播和常见的乘法
  18. Linux常用命令总结之(七)mkdir
  19. linux i217 v网卡驱动,英特尔网卡驱动下载_Intel英特尔I217I218I219系列网卡驱动官方下载 - 系统之家...
  20. ✖ subject may not be empty [subject-empty]

热门文章

  1. Redis集群原理详解
  2. cdr怎么转plt_win10系统怎么将cdr格式转换成plt?
  3. 自然语言处理技术的一些应用
  4. 软考中级软件设计师---下午题
  5. python在统计学中的应用论文_应用统计学论文
  6. Ureport2报表工具金额格式化
  7. 第九讲 函数间接展开成幂级数
  8. H3C Comware V7新增的RBAC
  9. 油田智能化远程监控系统_油田远程无线监控系统
  10. python学生管理系统毕业设计flask_python+flask实现简单的web端学生管理系统