zoukankan      html  css  js  c++  java
  • 移动架构-数据库分库和全版本升级

    在项目中,往往涉及到数据库的版本升级,通常会有两种升级方式,一种是纯代码实现,一种是脚本实现,这里使用脚本升级,这样的升级方式更便于维护

    思路

    全版本升级,重点在于数据的迁移,这里使用备份原数据库,新建数据库,增删字段,复制数据库的升级思路,其版本控制在脚本中声明,代码在写好之后基本是不会变动的,更利于维护

    SQLite修改表语句

    • 创建表 CREATE TABLE 表名 (列名 数据类型 限定符...)
    CREATE TABLE Table (ID INTEGER,NAME TEXT);
    
    • 修改表 ALTER TABLE ...
      命令允许用户重命名或添加新的字段在已有表中,不能从表中删除字段。并且只能在表的末尾添加字段
    ALTER TABLE tTable RENAME TO MyTable;
    
    • 添加一列 ALTER TABLE 表名 ADD COLUMN 列名 数据类型 限定符
    ALTER TABLE MyTable ADD COLUMN AGE INTEGER;
    
    • 删除表 DROP TABLE 表名
    DROP TABLE MyTable;
    

    更改表结构的方法:

    1. 当表中没有任何数据时
      删除表
    DROP TABLE MyTable;
    

    创建表

    CREATE TABLE MyTable ...
    
    1. 当表中有数据时
      将表名改为临时表
    ALTER TABLE MyTable RENAME TO _temp_MyTable;
    

    创建新表

    CREATE TABLE MyTable (....);
    

    导入数据

    INSERT INTO MyTable SELECT .., .. ,"用空来补充原来不存在的数据" FROM _temp_MyTable;
    

    删除临时表

    DROP TABLE _temp_MyTable;
    

    实现

    这里沿用设计的数据库,数据库分库已经在项目中包含了
    修改BaseDaoFactory,使其支持数据库分库

    public class BaseDaoFactory {
        private static final String TAG = "BaseDaoFactory";
        private String sqliteDatabasePath;
        private SQLiteDatabase sqLiteDatabase;
        private SQLiteDatabase userDatabase;
        private Map<String, BaseDao> map = Collections.synchronizedMap(new HashMap<String, BaseDao>());
        private static BaseDaoFactory instance = new BaseDaoFactory();
    
        public static BaseDaoFactory getInstance() {
            return instance;
        }
    
        private BaseDaoFactory() {
            File file = new File(Environment.getExternalStorageDirectory(), "update");
            if (!file.exists()) {
                file.mkdirs();
            }
            sqliteDatabasePath = file.getAbsolutePath() + "/user.db";
            openDatabase();
        }
    
        public synchronized <T extends BaseDao<M>, M> T getDataHelper(Class<T> clazz, Class<M> entityClass) {
            BaseDao baseDao = null;
            if (map.get(clazz.getSimpleName()) != null) {
                return (T) map.get(clazz.getSimpleName());
            }
            try {
                baseDao = clazz.newInstance();
                baseDao.init(entityClass, sqLiteDatabase);
                map.put(clazz.getSimpleName(), baseDao);
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
    
            return (T) baseDao;
        }
    
        public synchronized <T extends BaseDao<M>, M> T getUserHelper(Class<T> clazz, Class<M> entityClass) {
            openUserDatabase(getPath());
            BaseDao baseDao = null;
            //反射得到对象类型
            try {
                baseDao = clazz.newInstance();
                baseDao.init(entityClass, userDatabase);
                map.put(clazz.getSimpleName(), baseDao);
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            return (T) baseDao;
        }
    
        private void openDatabase() {
            //打开数据库,如果不存在则创建
            sqLiteDatabase = SQLiteDatabase.openOrCreateDatabase(sqliteDatabasePath, null);
        }
    
        public String getPath() {
            UserDao userDao = BaseDaoFactory.getInstance().getDataHelper(UserDao.class, User.class);
            if (userDao == null) {
                return null;
            }
            User currentUser = userDao.getCurrentUser();
            if (currentUser == null) {
                return null;
            }
            File file = new File(Environment.getExternalStorageDirectory(), "update");
            if (!file.exists()) {
                file.mkdirs();
            }
            File childFile = new File(file.getAbsolutePath(), currentUser.getUser_id());
            if(!childFile.exists()){
                childFile.mkdirs();
            }
            return file.getAbsolutePath() + "/" + currentUser.getUser_id() + "/logic.db";
    }
    
        private void openUserDatabase(String userDBPath) {
            //打开数据库,如果不存在则创建
            userDatabase = SQLiteDatabase.openOrCreateDatabase(userDBPath, null);
        }
    }
    

    创建数据库脚本

    public class CreateDb {
    
        //数据库表名
        private String name;
    
        //创建表的sql语句集合
        private List<String> sqlCreates;
    
        public CreateDb(Element ele) {
            name = ele.getAttribute("name");
            sqlCreates = new ArrayList<String>();
            NodeList sqls = ele.getElementsByTagName("sql_createTable");
            for (int i = 0; i < sqls.getLength(); i++) {
                String sqlCreate = sqls.item(i).getTextContent();
                this.sqlCreates.add(sqlCreate);
            }
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public List<String> getSqlCreates() {
            return sqlCreates;
        }
    
        public void setSqlCreates(List<String> sqlCreates) {
            this.sqlCreates = sqlCreates;
        }
    }
    

    数据库升级创建表脚本

    public class CreateVersion {
        //版本信息
        private String version;
    
        //创建数据库表脚本
        private List<CreateDb> createDbs;
    
        public CreateVersion(Element ele) {
            version = ele.getAttribute("version");
            createDbs = new ArrayList<CreateDb>();
            NodeList cs = ele.getElementsByTagName("createDb");
            for (int i = 0; i < cs.getLength(); i++) {
                Element ci = (Element) (cs.item(i));
                CreateDb cd = new CreateDb(ci);
                this.createDbs.add(cd);
            }
        }
    
        public String getVersion() {
            return version;
        }
    
        public void setVersion(String version) {
            this.version = version;
        }
    
        public List<CreateDb> getCreateDbs() {
            return createDbs;
        }
    
        public void setCreateDbs(List<CreateDb> createDbs) {
            this.createDbs = createDbs;
        }
    }
    

    复制单个文件(可更名复制)

    public class FileUtil {
        public static void CopySingleFile(String oldPathFile, String newPathFile) {
            try {
                int bytesum = 0;
                int byteread = 0;
                File oldfile = new File(oldPathFile);
                File newFile = new File(newPathFile);
                File parentFile = newFile.getParentFile();
                if (!parentFile.exists()) {
                    parentFile.mkdirs();
                }
                //文件存在时
                if (oldfile.exists()) {
                    InputStream inStream = new FileInputStream(oldPathFile);
                    FileOutputStream fs = new FileOutputStream(newPathFile);
                    byte[] buffer = new byte[1024];
                    while ((byteread = inStream.read(buffer)) != -1) {
                        bytesum += byteread; //字节数 文件大小
                        fs.write(buffer, 0, byteread);
                    }
                    inStream.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    更新数据库脚本

    public class UpdateDb {
        //数据库名称
        private String dbName;
        private List<String> sqlBefores;
        private List<String> sqlAfters;
    
        public UpdateDb(Element ele) {
            dbName = ele.getAttribute("name");
            sqlBefores = new ArrayList<String>();
            sqlAfters = new ArrayList<String>();
            NodeList sqlsBefore = ele.getElementsByTagName("sql_before");
            for (int i = 0; i < sqlsBefore.getLength(); i++) {
                String sql_before = sqlsBefore.item(i).getTextContent();
                this.sqlBefores.add(sql_before);
            }
            NodeList sqlsAfter = ele.getElementsByTagName("sql_after");
            for (int i = 0; i < sqlsAfter.getLength(); i++) {
                String sql_after = sqlsAfter.item(i).getTextContent();
                this.sqlAfters.add(sql_after);
            }
        }
    
        public String getDbName() {
            return dbName;
        }
    
        public void setDbName(String dbName) {
            this.dbName = dbName;
        }
    
        public List<String> getSqlBefores() {
            return sqlBefores;
        }
    
        public void setSqlBefores(List<String> sqlBefores) {
            this.sqlBefores = sqlBefores;
        }
    
        public List<String> getSqlAfters() {
            return sqlAfters;
        }
    
        public void setSqlAfters(List<String> sqlAfters) {
            this.sqlAfters = sqlAfters;
        }
    }
    

    升级更新数据库

    public class UpdateDbXml {
        //升级脚本列表
        private List<UpdateStep> updateSteps;
    
        //升级版本
        private List<CreateVersion> createVersions;
    
        public UpdateDbXml(Document document) {
            // 获取升级脚本
            NodeList updateSteps = document.getElementsByTagName("updateStep");
            this.updateSteps = new ArrayList<UpdateStep>();
            for (int i = 0; i < updateSteps.getLength(); i++) {
                Element ele = (Element) (updateSteps.item(i));
                UpdateStep step = new UpdateStep(ele);
                this.updateSteps.add(step);
            }
            //获取各升级版本
            NodeList createVersions = document.getElementsByTagName("createVersion");
            this.createVersions = new ArrayList<CreateVersion>();
            for (int i = 0; i < createVersions.getLength(); i++) {
                Element ele = (Element) (createVersions.item(i));
                CreateVersion cv = new CreateVersion(ele);
                this.createVersions.add(cv);
            }
        }
    
        public List<UpdateStep> getUpdateSteps() {
            return updateSteps;
        }
    
        public void setUpdateSteps(List<UpdateStep> updateSteps) {
            this.updateSteps = updateSteps;
        }
    
        public List<CreateVersion> getCreateVersions() {
            return createVersions;
        }
    
        public void setCreateVersions(List<CreateVersion> createVersions) {
            this.createVersions = createVersions;
        }
    }
    

    数据库升级脚本信息

    public class UpdateStep {
        //旧版本
        private String versionFrom;
    
        //新版本
        private String versionTo;
    
        //更新数据库脚本
        private List<UpdateDb> updateDbs;
    
        public UpdateStep(Element ele) {
            versionFrom = ele.getAttribute("versionFrom");
            versionTo = ele.getAttribute("versionTo");
            updateDbs = new ArrayList<UpdateDb>();
            NodeList dbs = ele.getElementsByTagName("updateDb");
            for (int i = 0; i < dbs.getLength(); i++) {
                Element db = (Element) (dbs.item(i));
                UpdateDb updateDb = new UpdateDb(db);
                this.updateDbs.add(updateDb);
            }
        }
    
        public List<UpdateDb> getUpdateDbs() {
            return updateDbs;
        }
    
        public void setUpdateDbs(List<UpdateDb> updateDbs) {
            this.updateDbs = updateDbs;
        }
    
        public String getVersionFrom() {
            return versionFrom;
        }
    
        public void setVersionFrom(String versionFrom) {
            this.versionFrom = versionFrom;
        }
    
        public String getVersionTo() {
            return versionTo;
        }
    
        public void setVersionTo(String versionTo) {
            this.versionTo = versionTo;
        }
    }
    

    数据库脚本管理

    public class UpdateManager {
        private static final String TAG = "UpdateManager";
        private static final String INFO_FILE_DIV = "/";
        private List<User> userList;
        private File parentFile = new File(Environment.getExternalStorageDirectory(), "update");
        private File bakFile = new File(parentFile, "backDb");
    
        public UpdateManager() {
            if (!parentFile.exists()) {
                parentFile.mkdirs();
            }
            if (!bakFile.exists()) {
                bakFile.mkdirs();
            }
    
        }
    
        public void checkThisVersionTable(Context context) {
            UserDao userDao = BaseDaoFactory.getInstance().getDataHelper(UserDao.class, User.class);
            userList = userDao.query(new User());
            UpdateDbXml xml = readDbXml(context);
            String thisVersion = getVersionName(context);
            CreateVersion thisCreateVersion = analyseCreateVersion(xml, thisVersion);
            try {
                executeCreateVersion(thisCreateVersion, true);
            } catch (Exception e) {
            }
    
        }
    
        //开始升级
        public void startUpdateDb(Context context) {
            UpdateDbXml updateDbxml = readDbXml(context);
            if (getLocalVersionInfo()) {
                //拿到当前版本
                String thisVersion = getVersionName(context);
                //拿到上一个版本
                String lastVersion = lastBackupVersion;
                UpdateStep updateStep = analyseUpdateStep(updateDbxml, lastVersion, thisVersion);
                if (updateStep == null) {
                    return;
                }
                List<UpdateDb> updateDbs = updateStep.getUpdateDbs();
                CreateVersion createVersion = analyseCreateVersion(updateDbxml, thisVersion);
                try {
                    //更新每个用户的数据库
                    for (User user : userList) {
                        String logicDbDir = parentFile.getAbsolutePath() + "/update" + "/" + user.getUser_id() + "/logic.db";
    
                        String logicCopy = bakFile.getAbsolutePath() + "/" + user.getUser_id() + "/logic.db";
                        FileUtil.CopySingleFile(logicDbDir, logicCopy);
                    }
                    //备份总数据库
                    String user = parentFile.getAbsolutePath() + "/user.db";
                    String user_bak = bakFile.getAbsolutePath() + "/user.db";
                    FileUtil.CopySingleFile(user, user_bak);
                    // 第二步:执行sql_before语句,删除以及备份相关旧表
                    executeDb(updateDbs, -1);
                    // 第三步:检查新表,创建新表
                    executeCreateVersion(createVersion, false);
                    Log.d(TAG, "第三步检查新表完成!");
                    // 第四步:从备份表中恢复数据,恢复后删除备份表
                    executeDb(updateDbs, 1);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                // 第五步:升级成功,删除备份数据库
                if (userList != null && !userList.isEmpty()) {
                    for (User user : userList) {
                        String logicDbDir = parentFile.getAbsolutePath() + "/update" + "/" + user.getUser_id() + ".db";
                        File file = new File(logicDbDir);
                        if (file.exists()) {
                            file.delete();
                        }
                    }
                }
                File userFileBak = new File(bakFile.getAbsolutePath() + "user_bak.db");
                if (userFileBak.exists()) {
                    userFileBak.delete();
                }
                Log.d(TAG, "升级成功");
            }
        }
    
        //根据建表脚本,核实一遍应该存在的表
        private void executeCreateVersion(CreateVersion createVersion, boolean isLogic) throws Exception {
            if (createVersion == null || createVersion.getCreateDbs() == null) {
                throw new Exception("createVersion or createDbs is null;");
            }
            for (CreateDb cd : createVersion.getCreateDbs()) {
                if (cd == null || cd.getName() == null) {
                    throw new Exception("db or dbName is null when createVersion;");
                }
                if (!"logic".equals(cd.getName())) {
                    continue;
                }
                // 创建数据库表sql
                List<String> sqls = cd.getSqlCreates();
                SQLiteDatabase sqlitedb = null;
                try {
                    // 逻辑层数据库要做多用户升级
                    if (userList != null && !userList.isEmpty()) {
                        // 多用户建新表
                        for (int i = 0; i < userList.size(); i++) {
                            // 获取db
                            sqlitedb = getDb(cd, userList.get(i).getUser_id());
                            executeSql(sqlitedb, sqls);
                            sqlitedb.close();
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    // 关闭数据库
                    if (sqlitedb != null) {
                        sqlitedb.close();
                    }
                }
            }
        }
    
    
        //执行针对db升级的sql集合 type:小于0为建表前,大于0为建表后
        private void executeDb(List<UpdateDb> updateDbs, int type) throws Exception {
            if (updateDbs == null) {
                throw new Exception("updateDbs is null;");
            }
            for (UpdateDb db : updateDbs) {
                if (db == null || db.getDbName() == null) {
                    throw new Exception("db or dbName is null;");
                }
                List<String> sqls = null;
                //更改表
                if (type < 0) {
                    sqls = db.getSqlBefores();
                } else if (type > 0) {
                    sqls = db.getSqlAfters();
                }
                SQLiteDatabase sqlitedb = null;
                try {
                    // 逻辑层数据库要做多用户升级
                    if (userList != null && !userList.isEmpty()) {
                        // 多用户表升级
                        for (int i = 0; i < userList.size(); i++) {
                            sqlitedb = getDb(db, userList.get(i).getUser_id());
                            executeSql(sqlitedb, sqls);
                            sqlitedb.close();
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (null != sqlitedb) {
                        sqlitedb.close();
                    }
                }
            }
        }
    
        //执行sql语句
        private void executeSql(SQLiteDatabase sqlitedb, List<String> sqls) throws Exception {
            // 检查参数
            if (sqls == null || sqls.size() == 0) {
                return;
            }
            // 事务
            sqlitedb.beginTransaction();
            for (String sql : sqls) {
                sql = sql.replaceAll("
    ", " ");
                sql = sql.replaceAll("
    ", " ");
                if (!"".equals(sql.trim())) {
                    try {
                        // Logger.i(TAG, "执行sql:" + sql, false);
                        sqlitedb.execSQL(sql);
                    } catch (SQLException e) {
                    }
                }
            }
            sqlitedb.setTransactionSuccessful();
            sqlitedb.endTransaction();
        }
    
    
        //新表插入数据
        private UpdateStep analyseUpdateStep(UpdateDbXml xml, String lastVersion, String thisVersion) {
            if (lastVersion == null || thisVersion == null) {
                return null;
            }
            // 更新脚本
            UpdateStep thisStep = null;
            if (xml == null) {
                return null;
            }
            List<UpdateStep> steps = xml.getUpdateSteps();
            if (steps == null || steps.size() == 0) {
                return null;
            }
            for (UpdateStep step : steps) {
                if (step.getVersionFrom() == null || step.getVersionTo() == null) {
                } else {
                    // 升级来源以逗号分隔
                    String[] lastVersionArray = step.getVersionFrom().split(",");
                    if (lastVersionArray != null && lastVersionArray.length > 0) {
                        for (int i = 0; i < lastVersionArray.length; i++) {
                            // 有一个配到update节点即升级数据
                            if (lastVersion.equalsIgnoreCase(lastVersionArray[i]) && step.getVersionTo().equalsIgnoreCase(thisVersion)) {
                                thisStep = step;
                                break;
                            }
                        }
                    }
                }
            }
            return thisStep;
        }
    
        //根据xml对象获取对应要修改的db文件
        private SQLiteDatabase getDb(UpdateDb db, String userId) {
            return getDb(db.getDbName(), userId);
        }
    
        private SQLiteDatabase getDb(CreateDb db, String userId) {
            return getDb(db.getName(), userId);
        }
    
        //创建数据库,获取数据库对应的SQLiteDatabase
        private SQLiteDatabase getDb(String dbname, String userId) {
            String dbfilepath = null;
            SQLiteDatabase sqlitedb = null;
            File file = new File(parentFile, userId);
            if (!file.exists()) {
                file.mkdirs();
            }
            if (dbname.equalsIgnoreCase("logic")) {
                dbfilepath = file.getAbsolutePath() + "/logic.db";// logic对应的数据库路径
            } else if (dbname.equalsIgnoreCase("user")) {
                dbfilepath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/user.db";// service对应的数据库
            }
            if (dbfilepath != null) {
                File f = new File(dbfilepath);
                f.mkdirs();
                if (f.isDirectory()) {
                    f.delete();
                }
                sqlitedb = SQLiteDatabase.openOrCreateDatabase(dbfilepath, null);
            }
            return sqlitedb;
        }
    
    
        //解析出对应版本的建表脚本
        private CreateVersion analyseCreateVersion(UpdateDbXml xml, String version) {
            CreateVersion cv = null;
            if (xml == null || version == null) {
                return cv;
            }
            List<CreateVersion> createVersions = xml.getCreateVersions();
            if (createVersions != null) {
                for (CreateVersion item : createVersions) {
                    // 如果表相同则要支持xml中逗号分隔
                    String[] createVersion = item.getVersion().trim().split(",");
                    for (int i = 0; i < createVersion.length; i++) {
                        if (createVersion[i].trim().equalsIgnoreCase(version)) {
                            cv = item;
                            break;
                        }
                    }
                }
            }
            return cv;
        }
    
        //读取升级xml
        private UpdateDbXml readDbXml(Context context) {
            InputStream is = null;
            Document document = null;
            try {
                is = context.getAssets().open("updateXml.xml");
                DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
                document = builder.parse(is);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (is != null) {
                    try {
                        is.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            if (document == null) {
                return null;
            }
            UpdateDbXml xml = new UpdateDbXml(document);
            return xml;
        }
    
        //获取APK版本号
        public String getVersionName(Context context) {
            String versionName = null;
            try {
                PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
                versionName = info.versionName;
            } catch (PackageManager.NameNotFoundException e) {
            }
            return versionName;
        }
    
        //保存下载APK版本信息
        public boolean saveVersionInfo(Context context, String newVersion) {
            boolean ret = false;
            FileWriter writer = null;
            try {
                writer = new FileWriter(new File(parentFile, "update.txt"), false);
                writer.write("V003" + INFO_FILE_DIV + "V002");
                writer.flush();
                ret = true;
            } catch (IOException e) {
            } finally {
                if (writer != null) {
                    try {
                        writer.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return ret;
        }
    
        //获取本地版本相关信息
        private String existVersion;
        private String lastBackupVersion;
    
        private boolean getLocalVersionInfo() {
            boolean ret = false;
            File file = new File(parentFile, "update.txt");
            if (file.exists()) {
                int byteread = 0;
                byte[] tempbytes = new byte[100];
                StringBuilder stringBuilder = new StringBuilder();
                InputStream in = null;
                try {
                    in = new FileInputStream(file);
                    while ((byteread = in.read(tempbytes)) != -1) {
                        stringBuilder.append(new String(tempbytes, 0, byteread));
                    }
                    String[] infos = stringBuilder.toString().split(INFO_FILE_DIV);
                    if (infos.length == 2) {
                        existVersion = infos[0];
                        lastBackupVersion = infos[1];
                        ret = true;
                    }
                } catch (Exception e) {
    
                } finally {
                    if (null != in) {
                        try {
                            in.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        in = null;
                    }
                }
            }
            return ret;
        }
    }
    

    模拟用户登录

    @DbTable("tb_user")
    public class User {
    
        public String name;
    
        public String password;
    
        public String user_id;
        public Integer status;
    
        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 String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    }
    
    public class UserDao extends BaseDao<User> {
        private static final String TAG = "UserDao";
        @Override
        public String createTable() {
            return "create table if not exists tb_user( name TEXT, password TEXT, user_id Text,status Integer);";
        }
    
        @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);
                update(user, where);
            }
            Log.d(TAG, "用户" + entity.getName() + "登录");
            entity.setStatus(1);
            return super.insert(entity);
        }
    
        //得到当前登录的User
        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;
        }
    }
    

    模拟用户下载数据

    @DbTable("tb_photo")
    public class Photo {
        public String time;
    
        public String path;
    
        public String getTime() {
            return time;
        }
    
        public void setTime(String time) {
            this.time = time;
        }
    
        public String getPath() {
            return path;
        }
    
        public void setPath(String path) {
            this.path = path;
        }
    }
    
    public class PhotoDao extends BaseDao<Photo> {
    
        @Override
        public String createTable() {
            return "create table if not exists tb_photo(
    " +
                    "                time TEXT,
    " +
                    "                path TEXT,
    " +
                    "                to_user TEXT
    " +
                    "                )";
        }
    }
    

    测试

    public class MainActivity extends AppCompatActivity {
    
        UpdateManager updateManager;
        UserDao baseDao;
        int i = 0;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            updateManager = new UpdateManager();
            baseDao = BaseDaoFactory.getInstance().getDataHelper(UserDao.class, User.class);
        }
    
        public void login(View view) {
    
            User user = new User();
            user.setName("V00" + (i++));
            user.setPassword("123456");
            user.setName("jack" + i);
            user.setUser_id("N000" + i);
            baseDao.insert(user);
            updateManager.checkThisVersionTable(this);
        }
    
        public void insert(View view) {
            Photo photo = new Photo();
            photo.setPath("data/data/my.jpg");
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
            photo.setTime(dateFormat.format(new Date()));
            PhotoDao photoDao = BaseDaoFactory.getInstance().getUserHelper(PhotoDao.class, Photo.class);
            photoDao.insert(photo);
        }
    
        public void write(View view) {
            //写入版本
            updateManager.saveVersionInfo(this, "V002");
        }
    
        public void update(View view) {
            updateManager.checkThisVersionTable(this);
            updateManager.startUpdateDb(this);
        }
    }
    

    在Assets文件夹加入升级脚本

    <!-- 请保证该文档一定是 UTF-8编码 -->
    <updateXml>
        <createVersion version="V003">
            <createDb name="user">
                <!-- 设备与软件关联信息 -->
                <sql_createTable>
                    create table if not exists tb_user(
                    name TEXT,
                    password TEXT,
                    loginName TEXT,
                    lastLoginTime,
                    user_id Integer primary key
                    );
                </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>
        <updateStep
            versionFrom="V002"
            versionTo="V003">
            <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>
    

    注意当前版本与升级脚本的一致

  • 相关阅读:
    TS之类的继承
    TS之函数及函数传参
    TS之数据类型
    Linux 协程
    设计模式 装饰器模式和代理模式
    C/C++ C和C++的区别
    C/C++ 内存分配方式
    Linux 进程间通信
    C/C++ RTTI
    Reactor设计模式
  • 原文地址:https://www.cnblogs.com/cj5785/p/10664611.html
Copyright © 2011-2022 走看看