Android数据库升级不丢失数据解决方案
在Android开发中,sqlite至关重要,增删查改不多说,难点在于,1,并发,多个线程同时操作数据库。2,版本升级时,如果数据库表中新加了个字段,如何在不删除表的情况下顺利过渡,从而不丢失数据。
数据库操作建议用ORM框架,简单高效。这里推荐xUtils,里面包含DBUtils。github地址:https://github.com/wyouflf/xUtils。关于DBUtils,它是这样介绍的:
- android中的orm框架,一行代码就可以进行增删改查;
- 支持事务,默认关闭;
- 可通过注解自定义表名,列名,外键,唯一性约束,NOT NULL约束,CHECK约束等(需要混淆的时候请注解表名和列名);
- 支持绑定外键,保存实体时外键关联实体自动保存或更新;
- 自动加载外键关联实体,支持延时加载;
- 支持链式表达查询,更直观的查询语义,参考下面的介绍或sample中的例子。
用单例方式获取数据库实例。
static DbUtils db = null; public static DbUtils getDb(Context context) { if (context == null) { context = DoctorApplication.getInstance(); } if (db == null) { db = DbUtils.create(context, "xUtils.db"); }); db.configAllowTransaction(true); return db; } db.configAllowTransaction(true); return db; } db.configAllowTransaction(true); 标示开启事务,这样多个线程操作数据库时就不会出现问题了。
数据库升级解决方案。首先创建一个实体类,对应数据库中的表。
@Table(name = "User") public class User { private int id; //主键ID,必须 private String uid; private String type; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getUid() { return uid; } public void setUid(String uid) { this.uid = uid; } }
如果由版本1到版本2中,User表中新增了个字段title,如何在不删除表User的情况下顺利过渡呢,我们知道,如果不作处理,数据库就会报错,没有列title。我们修改数据库的创建方式,实现升级接口。
db = DbUtils.create(context, "xUtils.db", 3, new DbUpgradeListener() { @Override public void onUpgrade(DbUtils db, int oldVersion, int newVersion) { if (newVersion > oldVersion) { updateDb(db, "User"); } } });
在updateDb方法中比较类的属性和之前版本数据库表中的字段,如果属性没有对应到字段,则添加相应的字段。
private static void updateDb(DbUtils db, String tableName) { try { Class<EntityBase> c = (Class<EntityBase>) Class.forName("com.henizaiyiqi.doctorassistant.entitis." + tableName);// 把要使用的类加载到内存中,并且把有关这个类的所有信息都存放到对象c中 if (db.tableIsExist(c)) { List<String> dbFildsList = new ArrayList<String>(); String str = "select * from " + tableName; Cursor cursor = db.execQuery(str); int count = cursor.getColumnCount(); for (int i = 0; i < count; i++) { dbFildsList.add(cursor.getColumnName(i)); } cursor.close(); Field f[] = c.getDeclaredFields();// 把属性的信息提取出来,并且存放到field类的对象中,因为每个field的对象只能存放一个属性的信息所以要用数组去接收 for (int i = 0; i < f.length; i++) { String fildName = f[i].getName(); if (fildName.equals("serialVersionUID")) { continue; } String fildType = f[i].getType().toString(); if (!isExist(dbFildsList, fildName)) { if (fildType.equals("class java.lang.String")) { db.execNonQuery("alter table " + tableName + " add " + fildName + " TEXT "); } else if (fildType.equals("int") || fildType.equals("long") || fildType.equals("boolean")) { db.execNonQuery("alter table " + tableName + " add " + fildName + " INTEGER "); } } } } } catch (Exception e) { } }
这样以后如果表中新增了字段,只需把数据库版本号加1,数据库就会自动升级一次,就能保证数据正常了。