[转载]Android数据库升级不丢失数据解决方案 - lsc183 - 博客园

[转载]Android数据库升级不丢失数据解决方案 – lsc183 – 博客园.

Android开发中,SQLite至关重要,增删查改不多说,难点在于,1,并发,多个线程同时操作数据库。2,版本升级时,如果数据库表中新加了个字段,如何在不删除表的情况下顺利过渡,从而不丢失数据。

数据库操作建议用ORM框架,简单高效。这里推荐xUtils,里面包含DBUtils。github地址:https://github.com/wyouflf/xUtils。关于DBUtils,它是这样介绍的:

  • Android中的orm框架,一行代码就可以进行增删改查;
  • 支持事务,默认关闭;
  • 可通过注解自定义表名,列名,外键,唯一性约束,NOT NULL约束,CHECK约束等(需要混淆的时候请注解表名和列名);
  • 支持绑定外键,保存实体时外键关联实体自动保存或更新;
  • 自动加载外键关联实体,支持延时加载;
  • 支持链式表达查询,更直观的查询语义,参考下面的介绍或sample中的例子。

用单例方式获取数据库实例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  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); 标示开启事务,这样多个线程操作数据库时就不会出现问题了。

数据库升级解决方案。首先创建一个实体类,对应数据库中的表。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
@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。我们修改数据库的创建方式,实现升级接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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方法中比较类的属性和之前版本数据库表中的字段,如果属性没有对应到字段,则添加相应的字段。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
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,数据库就会自动升级一次,就能保证数据正常了。

赞(0) 打赏
分享到: 更多 (0)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏