greenDAO的升级和存取

greenDAO 这么牛逼的库,很多人因为一些误解而放弃使用它,真的很可惜,同时也确实,有很多博客都在介绍 greenDAO 的使用,但是不得不说一些风气很不好,基本上都是官方文档上的 sample 自己照着抄一遍,然后就成文发布了,最让人困惑的一些问题一个都没涉及到。我大致总结了一下,不少人遇到的无非两个问题,升级和带 List 的 Object 的存取,算是记录一下。

数据库升级

有不少同学不选择 greenDAO 都是说它升级不好办,其实很简单。

  1. 创建 THDevOpenHelper 继承 DaoMaster.OpenHelper

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    /**
    * Created by Android Studio
    * User: Ailurus(ailurus@foxmail.com)
    * Date: 2015-07-08
    * Time: 11:29
    */

    public class THDevOpenHelper extends DaoMaster.OpenHelper {
    public THDevOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {
    super(context, name, factory);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    switch (oldVersion) {
    case 1:
    Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion);
    break;
    }
    }
    }
  2. Application里初始化

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    public class BaseApplication extends Application {
    private static DaoMaster daoMaster;
    private static DaoSession daoSession;

    @Override
    public void onCreate() {
    super.onCreate();
    THDevOpenHelper helper = new THDevOpenHelper(this, "test.db", null);
    SQLiteDatabase sqLiteDatabase = helper.getWritableDatabase();
    daoMaster = new DaoMaster(sqLiteDatabase);
    daoSession = daoMaster.newSession();
    }

    public static DaoMaster getDaoMaster() {
    return daoMaster;
    }

    public static DaoSession getDaoSession() {
    return daoSession;
    }
    }
  3. 假如是从版本1升级到版本2,就在 DaoMaster 里将 SCHEMA_VERSION 的值改为2(默认为1)

    1
    2
    3
    public class DaoMaster extends AbstractDaoMaster {
    public static final int SCHEMA_VERSION = 2;
    }
  4. THDevOpenHelperonUpgrade 方法里写需要执行的 SQL 语句,执行升级操作。这段 Java 代码,相信也都能看得懂。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    switch (oldVersion) {
    case 1:
    // 创建新表
    NewUserDao.createTable(db, true);

    // 加入新字段
    db.execSQL("ALTER TABLE 'USER' ADD 'USER_NAME' TEXT;");

    // 删除表
    UserDao.dropTable(db, true);
    Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion);
    break;
    }
    }

##List in Object 的存取

正常的基本数据类型的存取,相信有很多同学也都卡在这一块儿了,甚至听有人讲过,不能存取带 List 的 Object 的 orm 跟不用 orm 没差别。而恰恰 greenDAO 在这块儿做的非常好,代码看起来非常直观。废话不多说,直接上代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Star {
public String id;
public String userId;
public String userName;
public String userPic;
public String userIntro;
public String userCity;
public String userAddress;
public List<Klass> klassList;
}

public class Klass {
public String id;
}

这样的实体类要怎么存取?默认大家都是通过另外一个 Java Generator 工程里生成的 daoentity,对于这样的实体,我们只需这样做即可

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
public class CustomDaoGenerator {
public static void main(String[] args) throws Exception {
Schema schema = new Schema(1, "db.greendao.entity");
schema.enableKeepSectionsByDefault();
schema.setDefaultJavaPackageDao("db.greendao.dao");
addNote(schema);
new DaoGenerator().generateAll(schema, "/Users/liang/Documents/AndroidDemo/DaoGenerator");//这里替换成你想把 dao 和 entity 存储的路径
}

private static void addNote(Schema schema) {
createStarsTable(schema);
}

private static void createStarsTable(Schema schema) {
Entity star = schema.addEntity("Star");
star.addStringProperty("id").primaryKey();
star.addStringProperty("userId");
star.addStringProperty("userName");
star.addStringProperty("userPic");
star.addStringProperty("userIntro");
star.addStringProperty("userCity");
star.addStringProperty("userAddress");

Entity klass = schema.addEntity("Klass");
klass.addStringProperty("id");
Property klassInStar = klass.addStringProperty("star_id").notNull().getProperty();
klass.addToOne(star, klassInStar);
star.addToMany(klass, klassInStar);
}
}

然后我们可以看看生成的实体类与只有基本数据类型的实体类有什么区别

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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
public class Klass {
public String id;
/** Not-null value. */
public String star_id;

/** Used to resolve relations */
private transient DaoSession daoSession;

/** Used for active entity operations. */
private transient KlassDao myDao;

public Star star;
public String star__resolvedKey;


// KEEP FIELDS - put your custom fields here
// KEEP FIELDS END

public Klass() {
}

public Klass(String id, String star_id) {
this.id = id;
this.star_id = star_id;
}

/** called by internal mechanisms, do not call yourself. */
public void __setDaoSession(DaoSession daoSession) {
this.daoSession = daoSession;
myDao = daoSession != null ? daoSession.getKlassDao() : null;
}

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

/** Not-null value. */
public String getStar_id() {
return star_id;
}

/** Not-null value; ensure this value is available before it is saved to the database. */
public void setStar_id(String star_id) {
this.star_id = star_id;
}

/** To-one relationship, resolved on first access. */
public Star getStar() {
String __key = this.star_id;
if (star__resolvedKey == null || star__resolvedKey != __key) {
if (daoSession == null) {
throw new DaoException("Entity is detached from DAO context");
}
StarDao targetDao = daoSession.getStarDao();
Star starNew = targetDao.load(__key);
synchronized (this) {
star = starNew;
star__resolvedKey = __key;
}
}
return star;
}

public void setStar(Star star) {
if (star == null) {
throw new DaoException("To-one property 'star_id' has not-null constraint; cannot set to-one to null");
}
synchronized (this) {
this.star = star;
star_id = star.getId();
star__resolvedKey = star_id;
}
}

/** Convenient call for {@link AbstractDao#delete(Object)}. Entity must attached to an entity context. */
public void delete() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.delete(this);
}

/** Convenient call for {@link AbstractDao#update(Object)}. Entity must attached to an entity context. */
public void update() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.update(this);
}

/** Convenient call for {@link AbstractDao#refresh(Object)}. Entity must attached to an entity context. */
public void refresh() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.refresh(this);
}

// KEEP METHODS - put your custom methods here
// KEEP METHODS END

}

public class Klass {

public String id;
/** Not-null value. */
public String star_id;

/** Used to resolve relations */
private transient DaoSession daoSession;

/** Used for active entity operations. */
private transient KlassDao myDao;

public Star star;
public String star__resolvedKey;


// KEEP FIELDS - put your custom fields here
// KEEP FIELDS END

public Klass() {
}

public Klass(String id, String star_id) {
this.id = id;
this.star_id = star_id;
}

/** called by internal mechanisms, do not call yourself. */
public void __setDaoSession(DaoSession daoSession) {
this.daoSession = daoSession;
myDao = daoSession != null ? daoSession.getKlassDao() : null;
}

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

/** Not-null value. */
public String getStar_id() {
return star_id;
}

/** Not-null value; ensure this value is available before it is saved to the database. */
public void setStar_id(String star_id) {
this.star_id = star_id;
}

/** To-one relationship, resolved on first access. */
public Star getStar() {
String __key = this.star_id;
if (star__resolvedKey == null || star__resolvedKey != __key) {
if (daoSession == null) {
throw new DaoException("Entity is detached from DAO context");
}
StarDao targetDao = daoSession.getStarDao();
Star starNew = targetDao.load(__key);
synchronized (this) {
star = starNew;
star__resolvedKey = __key;
}
}
return star;
}

public void setStar(Star star) {
if (star == null) {
throw new DaoException("To-one property 'star_id' has not-null constraint; cannot set to-one to null");
}
synchronized (this) {
this.star = star;
star_id = star.getId();
star__resolvedKey = star_id;
}
}

/** Convenient call for {@link AbstractDao#delete(Object)}. Entity must attached to an entity context. */
public void delete() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.delete(this);
}

/** Convenient call for {@link AbstractDao#update(Object)}. Entity must attached to an entity context. */
public void update() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.update(this);
}

/** Convenient call for {@link AbstractDao#refresh(Object)}. Entity must attached to an entity context. */
public void refresh() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.refresh(this);
}

// KEEP METHODS - put your custom methods here
// KEEP METHODS END

}

存取的时候,按照下面的步骤来就可以了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
StarDao starDao = daoSession.getStarDao();
KlassDao klassDao = daoSession.getKlassDao();
Star star = new Star();
Klass klass1 = new Klass();
Klass klass2 = new Klass();
Klass klass3 = new Klass();
klass1.setStar(star);
klass2.setStar(star);
klass2.setStar(star);
klassDao.insert(klass1);
klassDao.insert(klass2);
klassDao.insert(klass3);
starDao.insert(star);
List<Star> stars = starDao.loadAll();
for (Star starEntity : stars) {
for (Klass klass : starEntity.getKlassList()) {
Log.i("id", klass.id);
}
}

OK,打完收工。