Android SQLite数据库版本更新

SQLite数据库版本升级

应用上线后会不断维护和更新版本,应用中使用数据库时,应用的升级难免会牵扯到数据库的升级。假如应用从V1.0更新到V2.0,到现在的V3.0。V1.0版本中只有一张Product商品表。到V2.0版本时,Product中需要增加一个字段salesperson。到V3.0时,增加了一张Shop表。那么需要考虑一个问题,应用的用户很多,有老用户,有新用户。用户使用可能使用不同版本的应用,现在有了V3.0版本。那么可能有新用户直接安装V3.0。可能有从V2.0更新到V3.0的,也可能有V1.0更新到V3.0的。我们知道SQLiteOpenHelper类有onCreate(SQLiteDatabase db)和onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)方法。onCreate()方法是在数据库版本号为0的时候调用,只调用一次。onUpgrade()方法是数据库版本更新的时候调用。
正常情况下:

  • 直接安装V3.0,只走onCreat();不走onUpgrade()。
  • V1.0 - V3.0,只走onUpgrade(),不走onCreat()。
  • V2.0 - V3.0,只走onUpgrade(),不走onCreat()。

那么表的更新放在哪个方法中呢?但是想想,要么放在onCreat()方法要么onUpgrade()中。

如果直接安装V3.0,那么可以完全放在onCreat()中。因为onUpgrade()方发不能被调用,所以需要全部写在onCreat()方法中。但是考虑到V1.0 —>V3.0或V2.0 —>V3.0时onCreat()不能在被调用了,所以更新部分不能写在onCreat()中,对于V1.0 —>V3.0或V2.0 —>V3.0更新可以写在onUpgrade()方法中,因为onUpgrad()方发得到调用。

既然不能完全写在onCreat()中,那么能全部写在onUpgrade()方法中吗?对于V1.0 —>V3.0或V2.0 —>V3.0的更新Product表已经存在了,所以不需要在创建Product表了,而是需要更新它,所以更新部分需要写在onUpgrad()方法中。即不能全部的代码写在onUpgrade()方法中。

考虑到各种情况,不能完全写在onCreat()方法中,也不能完全写在onUpgrade()方法中,经过上面的分析,更新部分一定需要写在onUpgrade()方法中。但时,onUpgrade()方法只在数据库版本升级后才被调用啊,在直接安装V3.0的时候不被调用,那怎么办?我们可以手动调用啊。(哈哈哈,问题解决)。那在哪里调用呢?当然是在onCreat()方法中调用。

经过上面的分析,数据库更新部分是写在onUpgrade()方发中的。首次创建数据库时,需要创键的表可以下在onCreat()方法中。这是符合以前思路的。上面分析的关键点在于,在onCreat()方法中手动调用一次onUpgrade()方法。这是思维的突破,以前总是认为onUpgrade()只能在数据库版本升级时由系统调用。这样把数库更新的部分放在onUpgrade()方法中。由于在onCreat()方法中手动调用了一次onUpgrade()方法,所以直接直接安装V3.0的版本的用户,数库更新部分的代码也会被执行。而从V1.0—>V3.0版本和V2.0—>V3.0的,onCreat()不会被调用,但由于数据库版本升级了,所以onUpgrade()方法会被调用。
接下来看代码:先看DBOpenHelper类

public class DBOpenHelper extends SQLiteOpenHelper {

    private Context mContext ;
    public static String batabaseName = "message.db";
    public static String tableName = "message" ;
    public static String product_name = "product_name";
    public static String product_type = "product_type";
    public static String sale_price = "sale_price";
    public static String purcgase_price = "purcgase_price";
    public static String regist_date = "regist_date";
    public static String sendname = "sendname";

    private final int INITIAL_VERSION = 1 ; // 初始版本号
    public static int NEW_VERSION = 0 ;       // 最新的版本号

    /**
     * 经测试发现version不能小于等于0 否则报错
     * @param context
     * @param name
     * @param factory
     * @param version
     */
    public DBOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
        mContext = context ;
        NEW_VERSION = version ;
    }

    public DBOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version, DatabaseErrorHandler errorHandler) {
        super(context, name, factory, version, errorHandler);
        mContext = context ;
        NEW_VERSION = version ;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        String createTable = "create table if not exists "+ tableName + "( product_id char(4) primary key , product_name varchar(100) not null , product_type varchar(32) not null , " +
                             "sale_price int , purcgase_price int , regist_date date )";
        db.execSQL(createTable);
        Log.d("TAG" , "数据库创建");
        onUpgrade( db , INITIAL_VERSION , NEW_VERSION );
    }

    @Override
    public void onUpgrade( SQLiteDatabase db , int oldVersion , int newVersion ) {
        update(db, oldVersion, newVersion);
    }

    /**
     * 数据库版本递归更新
     * @param oldVersion 数据库当前版本号
     * @param newVersion 数据库升级后的最终版本号
     */
    public void update(SQLiteDatabase db, int oldVersion, int newVersion) {
        Log.d("TAG" , "onUpgrade oldVersion = "+ oldVersion + "  newVersion = "+ newVersion);
        Upgrade upgrade = null;
        if (oldVersion < newVersion) {
            oldVersion++;
            upgrade = VersionFactory.getUpgrade(oldVersion); // 重点
            if (upgrade == null) {
                return;
            }
            upgrade.update(db);
            update(db, oldVersion, newVersion); // 递归调用
        }
    }

    @Override
    public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        super.onDowngrade(db, oldVersion, newVersion);
        Log.d("TAG" , "onDowngrade oldVersion = "+ oldVersion + "  newVersion = "+ newVersion);
    }
}

DBOpenHelper继承SQLiteOpenHelper类。onCreate()方法调用了onUpgrade()方法。update()方法主要负责版本更新了,里面使用了到了递归调用。VersionFactory类是生产Upgrade类的工厂类。代码如下:

public class VersionFactory {

    static Set<String> list = new LinkedHashSet<>();

    static {  // 以后没添加一个版本,就在这个集合中添加类的全路径(必须是全路径)
        list.add("com.dbsql.db.VersionSecond");
        list.add("com.dbsql.db.VersionThird");
    }

    /**
     * 根据数据库版本号获取对应的对象
     * @param i
     * @return
     */
    public static Upgrade getUpgrade(int i) {
        Upgrade upgrade = null ;
        if (null != list && list.size() > 0) {
            try {
                for (String className : list) {
                    Class<?> cls = null;
                    cls = Class.forName(className);
                    if (Upgrade.class == cls.getSuperclass()) { // 首先父类是Upgrade类
                        VersionCode versionCode = cls.getAnnotation(VersionCode.class);
                        if (null == versionCode) {
                            throw new IllegalStateException(cls.getName() + "类必须使用VersionCode类注解");
                        } else {
                            if (i == versionCode.value()) { // 等于当前要操作的版本。
                                upgrade = (Upgrade) cls.newInstance(); // 根据class获取实例,并向上转为父类型。
                                break;
                            }
                        }
                    }
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
                throw new IllegalStateException("没有找到类名,请检查list里面添加的类名是否正确!");
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return upgrade;
    }

    /**
     * 得到当前数据库版本
     * @return
     */
    public static int getCurrentDBVersion() {
        return list.size() + 1;
    }
}

/**
*注解类
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface VersionCode {
    int value() default 1;
}

public abstract class Upgrade {
    public abstract void update(SQLiteDatabase db);
}

/**
*第二版本要做的更新
*/
@VersionCode(2)
public class VersionSecond extends Upgrade {
    @Override
    public void update(SQLiteDatabase db) {
        String sql = "alter table "+DBOpenHelper.tableName + " add column salesperson char(10) " ;
        db.execSQL(sql);
    }
}

/**
*第三版本要做的更新
*/
@VersionCode(3)
public class VersionThird extends Upgrade{
    @Override
    public void update(SQLiteDatabase db) {
        String sql = "create table if not exsits Shop ( shop_id char(4) primary key , shop_name text )" ;
        db.execSQL(sql);
    }
}

V1.0—>V3.0的过程是,先从V1.0—>V2.0,再从V2.0—>V3.0。
V2.0—>V3.0的过程是,从V2.0—>V3.0。
直接安装V3.0版本的过程是,先常见V1.0版本的表,从V1.0—>V2.0,最后从V2.0—>V3.0。

项目地址

猜你喜欢

转载自blog.csdn.net/xiaol206/article/details/80161363