本篇来讲解,如何实现多用户分库,在一些项目中,存在多用户登录的情况,比如QQ ,切换qq的登录账号,一些用户的操作需要存到数据库中,如果我们存到同一张表中,查询修改都非常麻烦。在比如一些类似滴滴打车之类的,APP 有用户端 和 司机端,现在大部分APP 都是用户端 和 司机端 在一个APP 上操作,如果我们都存在tb_car 的一个数据库表中,那么就需要判断是否是司机等一些操作,如果再加上权限的一些操作对数据库表的操作会相当的麻烦。
image.png
如何实现分库呢?
看下图:
image.png
如上图所示,我们可以将用户登录的信息存到tb_user的表中,然后根据当前登录的用户state = 1 来生成用户私有数据库的路径和私有的数据库连接池,然后创建用户的私有数据库,这样用户的所有操作,就可以存到用户的私有数据库中,当切换另一个用户时,操作的是另一个用户的私有数据库,当切换回之前的用户时,可以根据之前用户的私有数据库,恢复之前用户的数据。
代码实现分库
在BaseDao 基础上我们新建一个UserDao,用来实现改变用户的登录状态和获取当前登录的用户。用于维护公有数据,新登录的状态state = 1;之前登录过的用户状态state = 0
public class UserDao extends BaseDao<User> {
private static final String TAG = "UserDao";
@Override
public long insert(User entity) {
// 查到表中的所有的用户记录
List<User> userList = query(new User());
User where;
for (User user : userList) {
// 将所有的用户的登陆状态 改为 0
where = new User();
where.id = user.id;
user.state = "0";
Log.e(TAG, "用户: " + user.name + " 未登录");
update(user, where);
}
Log.e(TAG, "用户: " + entity.name + " 登录");
// 将当前用户的状态给为 1 然后插入
entity.state = "1";
return super.insert(entity);
}
/**
* 得到当前登录的user
*/
public User getCurrentUser() {
User user = new User();
user.state = "1";
List<User> query = query(user);
if (query != null && query.size() > 0) {
return query.get(0);
}
return null;
}
}
根据当前登录的用户,生成当前用户的私有数据库的路径(可以是在某个文件夹下: 用户id/login.db)
public enum PrivateDataBaseEnums {
database("");
private String value;
PrivateDataBaseEnums(String value) {
}
// 用于生产路径
public String getValue() {
UserDao baseDao = BaseDaoFactory.getInstance().getBaseDao(UserDao.class, User.class);
User currentUser = baseDao.getCurrentUser();
if (currentUser != null) {
File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath());
if (!file.exists()) {
file.mkdirs();
}
return file.getAbsolutePath() + "/n" + currentUser.id + "_login.db";
}
return null;
}
}
之后我们为当前登录的用户建立私有数据库的连接池,在之前的BaseDaoFactory的基础上,我们新建一个 用户私有数据库的BaseDaoSubFactory 工厂继承BaseDaoFactory,当用户在进行数据库操作时,用来生产BaseDao对象
/**
* 生产basedao 对象
*
* @param entityClass
* @param <T> User 对象
* @param <M> BaseDao {@link BaseDao}
* @return
*/
public synchronized <M extends BaseDao<T>, T> M getSubBaseDao(Class<M> daoClass, Class<T> entityClass) {
BaseDao baseDao = null;
if (map.get(PrivateDataBaseEnums.database.getValue()) != null) {// 判断当前用户私有的数据库是否存在
return (M) map.get(PrivateDataBaseEnums.database.getValue());
}
// 如果不存在则创建当前用户的私有数据库
Log.e("jett", "生成数据库文件的位置:" + PrivateDataBaseEnums.database.getValue());
subSQLiteDatabase = SQLiteDatabase.openOrCreateDatabase(PrivateDataBaseEnums.database.getValue(), null);
try {
baseDao = daoClass.newInstance();
baseDao.init(subSQLiteDatabase, entityClass);
map.put(PrivateDataBaseEnums.database.getValue(), baseDao);
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return (M) baseDao;
}
这样我们就可以用getSubBaseDao 来进行数据库的操作,数据都会存到用户的私有数据库中去。
对代码进行测试
BaseDao userDao = BaseDaoFactory.getInstance().getBaseDao(UserDao.class, User.class);
/** 模仿用户切换登录的操作 */
public void clickSubLogin(View view) {
// 登录以后 服务器返回用户信息
prim.com.lib_db.sub_qlite.User user = new prim.com.lib_db.sub_qlite.User();
user.id = i;
user.name = "张三" + (++i);
user.pass = "123";
// 在公共信息中插入到公共数据库中
userDao.insert(user);
}
/** 模仿用户登录后操作,将数据存到私有数据库中 */
public void clickSubInster(View view) {
// 插入私有数据库
Photo photo = new Photo();
photo.path = "data/data/img.jpg";
photo.time = "2018-4-5";
// 插入到当前登录的用户的私有数据库中
PhotoDao subBaseDao = BaseDaoSubFactory.getInstance().getSubBaseDao(PhotoDao.class, Photo.class);
subBaseDao.insert(photo);
}
这里注意 PhotoDao extends BaseDao
运行项目:
image.png
点击两次登录,可以看到 张三1 state = 0 成了未登录的状态,而张三2 state = 1 变成已登录的状态。
image.png
我们在看下tb_user表中的数据是:
image.png
我们点击分库插入按钮,然后去存放私有数据库的路径下,有没有创建用户的私有数据库,我这里直接将数据库存到sd卡中了。下图说明,为我们创建了用户的私有数据库了。
image.png
然后我们,去看私有数据库中的 tb_photo 表中是否有数据
image.png可以看到确实有数据存在。
然后我们在点击登录按钮和分库插入按钮。
image.png
image.png
OK,可以看到,新登录的用户私有数据库创建成功了。
多点击两次分库插入按钮,然后我们去n2_login.db 看下tb_photo 表中的数据。
image.png
然后我们再看一下上一个登录用户的n1_login.db tb_photo 表中的数据.
image.png
ok,这样我们就完成了,多用户分库。多用户分库的好处,在用户登录的时候,我们就不去再去同一个表中查询这个用户是什么用户了,直接操作用户,存到用户的私有数据库中,用户退出再登录后可直接从用户的私有数据库中恢复用户的数据。在大型的项目中一定会用到这个功能。
网友评论