[转载]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,数据库就会自动升级一次,就能保证数据正常了。