您的位置:首页 > 移动开发 > Android开发

Android源码分析之仿OrmLite数据库框架

2017-10-21 18:21 525 查看

1 介绍

  Ormlite,英文全称是Object Relational Mapping,意思是对象关系映射。前面写过使用的文章,Android进阶之数据库框架ormlite使用。我们也参考着写一个轻量级的数据库访问框架。

2 使用方法

(1)在 gradle 中引入:

compile 'com.guan.codelibs:lightsqlite:1.0.0'


(2)UserBean

@DbTable("tb_user")
public class UserBean {
public int user_id=0;
@DbFiled("user_name")
public String name;
@DbFiled("user_password")
public String password;

public UserBean( ) {
}
public UserBean(Integer user_id, String name, String password) {
this.user_id= user_id;
this.name = name;
this.password = password;
}
}


(3)UserDao

public class UserDao extends BaseDao {
public UserDao() {
}
@Override
protected String createTable() {
return "create table if not exists tb_user(user_id int, user_name varchar(20), user_password varchar(10))";
}
@Override
public List query(String sql) {
return null;
}
}


(4)UserInfoService

public class UserInfoService {
private IBaseDao<UserBean> userDao;

public UserInfoService() {
userDao = BaseDaoFactory.getInstance().getDataHelper(UserDao.class, UserBean.class);
}
public void deleteOneUser(UserBean userBean) {
userDao.delete(userBean);
}
public void saveUser(UserBean userBean) {
userDao.insert(userBean);
}
public void updateUser(UserBean userBean, UserBean where) {
userDao.update(userBean, where);
}
public List<UserBean> getUsers(UserBean where) {
return userDao.query(where);
}
}


(5)MainActivity

public class MainActivity extends AppCompatActivity {
private static final String TAG = "tag";
private UserInfoService mUserInfoService;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initService();
}

private void initService() {
mUserInfoService = new UserInfoService();
}
public void save(View view) {
for (int i = 0; i < 10; i++) {
UserBean userBean = new UserBean(i, "android", "123456");
mUserInfoService.saveUser(userBean);
}
}
public void delete(View view) {
UserBean userBean = new UserBean(2, "android", "123456");
mUserInfoService.deleteOneUser(userBean);
}
public void update(View view) {
UserBean userBean = new UserBean(1, "ios", "654321");
UserBean where = new UserBean();
where.setName("android");
mUserInfoService.updateUser(userBean, where);
}
public void queryList(View view) {
UserBean where = new UserBean();
where.setName("android");
where.setUser_Id(5);
List<UserBean> list = mUserInfoService.getUsers(where);
Log.e(TAG, "查询到:" + list.size() + "条数据");
}
}


3 源码地址

github项目地址:CodeLibs/lib-lightsqlite/

4 框架图分析



5 使用到的知识点

泛型

注解,Java进阶之注解

反射,Java进阶之反射

数据库语句拼接

单例模式

简单工厂模式

模板方法模式

6 扩展-数据库分库实现

6.1 使用方法

(1)在 gradle 中引入:

compile 'com.guan.codelibs:lightsqlite:1.0.1'


(2)参考demo-多用户登录/插入用户照片数据

lib-lightsqlite/lightsqlite-example/



(3)结果演示



6.2 框架图分析



6.3 核心代码

/**
* 多用户登录,将其他用户更改为未登录状态
* @param view
*/
public void login(View view) {
++i;
UserBean user = new UserBean();
user.setName("V00" + i);
user.setPassword("123456");
user.setUser_Id("V" + i);
mUserInfoService.saveUser(user);
updateManager.checkThisVersionTable(this);
}


@Override
public Long insert(UserBean entity) {
UserBean query = new UserBean();
query.setStatus(1);
List<UserBean> userList = query(query);

for (UserBean user : userList) {
UserBean where = new UserBean();
where.setUser_Id(user.getUser_Id());
user.setStatus(0);
update(user, where);
Log.i(TAG, "用户" + user.getName() + "更改为未登录状态");
}

Log.i(TAG, "用户" + entity.getName() + "登录");
entity.setStatus(1);
return super.insert(entity);
}


6.4 拓展–如何使用到当前项目中

  目前项目使用的是OrmLite开源库,user_id存储在本地,可以通过以下方式实现数据库分库:

public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
String user_id = ;//获取到user_id
private static final String DATABASE_NAME = user_id + "fungovod.db";

private static final int DATABASE_VERSION = 1;
}


7 数据库升级更新如何保留原来数据方案

7.1 确定相邻版本的差别,从版本1开始依次迭代更新,先执行v1到v2,再v2到v3……

(1)优点:每次更新数据库的时候只需要在onUpgrade方法的末尾加一段从上个版本升级到新版本的代码,易于理解和维护。

(2)缺点:当版本变多之后,多次迭代升级可能需要花费不少时间,增加用户等待;

(3)举例:云图项目中使用到的—ORMLite升级方案

@Override
public void onUpgrade(SQLiteDatabase db, ConnectionSource connectionSource, int oldVersion, int newVersion) {
if(oldVersion < 2){
DatabaseUtil.upgradeTable(db,connectionSource,A.class,DatabaseUtil.OPERATION_TYPE.ADD);
DatabaseUtil.upgradeTable(db,connectionSource,B.class,DatabaseUtil.OPERATION_TYPE.DELETE);
}
if(oldVersion < 3){
DatabaseUtil.upgradeTable(db,connectionSource,C.class,DatabaseUtil.OPERATION_TYPE.ADD);
}
onCreate(db,connectionSource);
}


Android数据库ORMLite版本升级及数据的迁移

7.2 为每个版本确定与现在数据库的差别,为每个case撰写专门的升级代码。

(1)优点:可以保证每个版本的用户都可以在消耗最少的时间升级到最新的数据库而无需做无用的数据多次转存。

(2)缺点:强迫开发者记忆所有版本数据库的完整结构,且每次升级时onUpgrade方法都必须全部重写。

7.3 脚本设计(思路)

7.3.1 使用方法

(1)在 gradle 中引入:

compile 'com.guan.codelibs:lightsqlite:1.0.1'


(2)参考demo-写入最新版本号/更新数据库

lib-lightsqlite/lightsqlite-example/



(3)脚本

<!-- 请保证该文档一定是 UTF-8编码 -->
<updateXml>
<createVersion version="V1">
<createDb name="user">
<!-- 设备与软件关联信息 -->
<sql_createTable>
create table if not exists tb_user(
user_id varchar(20), user_name varchar(20), user_password varchar(10), user_status Integer);
</sql_createTable>
</createDb>
<createDb name="logic">
<!-- 设备与软件关联信息 -->
<sql_createTable>
create table if not exists tb_photo(
time TEXT,
path TEXT,
to_user TEXT,
sendTime TEXT
);
</sql_createTable>
</createDb>
</createVersion>

<!-- V1升级到V3 -->
<updateStep
versionFrom="V1"
versionTo="V3">
<updateDb name="logic">
<sql_before>alter table tb_photo rename to bak_tb_photo;</sql_before>
<sql_after>
insert into tb_photo(time,
path)
select time,path
from bak_tb_photo;
</sql_after>
<sql_after>
drop table if exists bak_tb_photo;
</sql_after>
</updateDb>
<updateDb name="user">
<sql_before>alter table tb_user rename to bak_t_user;</sql_before>
<sql_after>
insert into tb_user(name,
password)
select name,password
from bak_tb_user;
</sql_after>
<sql_after>
drop table if exists bak_t_user;
</sql_after>
</updateDb>
</updateStep>

<!-- V2升级到V3 -->
<updateStep
versionFrom="V2"
versionTo="V3">
<updateDb name="logic">
<sql_before>alter table tb_photo rename to bak_tb_photo;</sql_before>
<sql_after>
insert into tb_photo(time,
path)
select time,path
from bak_tb_photo;
</sql_after>
<sql_after>
drop table if exists bak_tb_photo;
</sql_after>
</updateDb>
<updateDb name="user">
<sql_before>alter table tb_user rename to bak_t_user;</sql_before>
<sql_after>
insert into tb_user(name,
password)
select name,password
from bak_tb_user;
</sql_after>
<sql_after>
drop table if exists bak_t_user;
</sql_after>
</updateDb>
</updateStep>
</updateXml>


9 扩展-其他

9.1 数据库的操作类型有哪些?

(1)openOrCreateDatabase(String path);

(2)继承SqliteOpenHelper类对数据库及其版本进行管理(onCreate,onUpgrade)

当在程序当中调用这个类的方法getWritableDatabase()或者getReadableDatabase();的时候才会打开数据库。如果当时没有数据库文件的时候,系统就会自动生成一个数据库。

9.2 操作的类型:增删改查CRUD

(1)直接操作SQL语句:SQliteDatabase.execSQL(sql);

(2)面向对象的操作方式:SQLiteDatabase.insert(table, nullColumnHack, ContentValues);

9.3 如何导入外部数据库?

  一般外部数据库文件可能放在SD卡或者res/raw或者assets目录下面。写一个DBManager的类来管理,数据库文件搬家,先把数据库文件复制到”/data/data/包名/databases/”目录下面,然后通过db.openOrCreateDatabase(db文件),打开数据库使用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: