GreenDAO 是一个轻量级的 ORM(对象关系映射)框架,专为 Android 平台设计。它帮助开发者更方便地操作 SQLite 数据库,而无需编写大量的 SQL 语句。以下是 GreenDAO 的主要使用方面:
1. 环境准备
在使用 GreenDAO 之前,需要在项目中引入依赖。通常可以通过 Gradle 来管理依赖。
添加依赖
在 build.gradle
文件中添加 GreenDAO 的依赖:
groovy
dependencies {
implementation 'org.greenrobot:greendao:3.3.0' // 请使用最新版本
}
2. 实体类生成
GreenDAO 使用注解处理器来自动生成实体类和 DAO(Data Access Object)类。你需要定义实体类,并使用 GreenDAO 的注解。
定义实体类
java
@Entity
public class User {
@Id
private Long id;
@Property
private String name;
@Property
private String email;
// Getters and Setters
}
3. DAO 生成
使用 GreenDAO 的注解处理器生成 DAO 类。你需要在项目中配置 GreenDAO 的注解处理器。
配置注解处理器
在 build.gradle
文件中添加注解处理器:
groovy
dependencies {
implementation 'org.greenrobot:greendao:3.3.0'
annotationProcessor 'org.greenrobot:greendao-generator:3.3.0'
}
4. 数据库管理
GreenDAO 提供了一个 DaoMaster
和 DaoSession
类来管理数据库连接和操作。
初始化数据库
java
public class MyApplication extends Application {
private DaoMaster.DevOpenHelper helper;
private DaoMaster daoMaster;
private DaoSession daoSession;
@Override
public void onCreate() {
super.onCreate();
helper = new DaoMaster.DevOpenHelper(this, "mydb.db", null);
daoMaster = new DaoMaster(helper.getWritableDatabase());
daoSession = daoMaster.newSession();
}
public DaoSession getDaoSession() {
return daoSession;
}
public DaoMaster getDaoMaster() {
return daoMaster;
}
}
5. 插入数据
使用 Dao
类的 insert
方法插入数据。
插入数据示例
java
public class MainActivity extends AppCompatActivity {
private UserDao userDao;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyApplication app = (MyApplication) getApplication();
userDao = app.getDaoSession().getUserDao();
User user = new User(null, "John Doe", "john@example.com");
userDao.insert(user);
}
}
6. 查询数据
使用 Dao
类的 queryBuilder
方法构建查询条件。
查询数据示例
java
public class MainActivity extends AppCompatActivity {
private UserDao userDao;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyApplication app = (MyApplication) getApplication();
userDao = app.getDaoSession().getUserDao();
// 查询所有用户
List<User> users = userDao.loadAll();
for (User user : users) {
Log.d("MainActivity", "User: " + user.getName());
}
// 根据条件查询
List<User> usersWithName = userDao.queryBuilder()
.where(UserDao.Properties.Name.eq("John Doe"))
.list();
for (User user : usersWithName) {
Log.d("MainActivity", "User with name John Doe: " + user.getEmail());
}
}
}
7. 更新数据
使用 Dao
类的 update
方法更新数据。
更新数据示例
java
public class MainActivity extends AppCompatActivity {
private UserDao userDao;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyApplication app = (MyApplication) getApplication();
userDao = app.getDaoSession().getUserDao();
// 查询用户
User user = userDao.queryBuilder()
.where(UserDao.Properties.Name.eq("John Doe"))
.unique();
if (user != null) {
// 更新用户信息
user.setEmail("john_new@example.com");
userDao.update(user);
}
}
}
8. 删除数据
使用 Dao
类的 delete
方法删除数据。
删除数据示例
java
public class MainActivity extends AppCompatActivity {
private UserDao userDao;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyApplication app = (MyApplication) getApplication();
userDao = app.getDaoSession().getUserDao();
// 查询用户
User user = userDao.queryBuilder()
.where(UserDao.Properties.Name.eq("John Doe"))
.unique();
if (user != null) {
// 删除用户
userDao.delete(user);
}
}
}
9. 关系映射
GreenDAO 支持一对一、一对多和多对多的关系映射。
一对一关系
java
@Entity
public class User {
@Id
private Long id;
@Property
private String name;
@ToOne(joinProperty = "addressId")
private Address address;
@Property
private Long addressId;
// Getters and Setters
}
@Entity
public class Address {
@Id
private Long id;
@Property
private String street;
// Getters and Setters
}
一对多关系
java
@Entity
public class User {
@Id
private Long id;
@Property
private String name;
@ToMany(referencedJoinProperty = "userId")
private List<Note> notes;
// Getters and Setters
}
@Entity
public class Note {
@Id
private Long id;
@Property
private String content;
@Property
private Long userId;
// Getters and Setters
}
10. 事务管理
GreenDAO 提供了事务管理功能,确保数据的一致性和完整性。
事务管理示例
java
public class MainActivity extends AppCompatActivity {
private UserDao userDao;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyApplication app = (MyApplication) getApplication();
userDao = app.getDaoSession().getUserDao();
userDao.getSession().runInTx(new Runnable() {
@Override
public void run() {
User user1 = new User(null, "John Doe", "john@example.com");
User user2 = new User(null, "Jane Smith", "jane@example.com");
userDao.insert(user1);
userDao.insert(user2);
}
});
}
}
11. 数据库迁移
当数据库结构发生变化时,需要进行数据库迁移。GreenDAO 提供了 DevOpenHelper
的子类 MigrationHelper
来帮助进行数据库迁移。
数据库迁移示例
java
public class MyApplication extends Application {
private DaoMaster.DevOpenHelper helper;
private DaoMaster daoMaster;
private DaoSession daoSession;
@Override
public void onCreate() {
super.onCreate();
helper = new DaoMaster.DevOpenHelper(this, "mydb.db", null) {
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
MigrationHelper.migrate(db, User.class, Address.class);
}
};
daoMaster = new DaoMaster(helper.getWritableDatabase());
daoSession = daoMaster.newSession();
}
public DaoSession getDaoSession() {
return daoSession;
}
public DaoMaster getDaoMaster() {
return daoMaster;
}
}
12.Q&A
1. 数据对象 id
如果没有设置会有什么问题
在 GreenDAO 中,id
字段通常被标记为 @Id
,表示它是主键。如果 id
没有设置,可能会导致以下问题:
- 无法使用
insertOrReplace
方法 :insertOrReplace
方法需要根据id
判定是插入新记录还是替换现有记录。如果id
没有设置,会导致无法正确执行该方法。 - 数据唯一性问题 :主键字段通常用于保证数据的唯一性。如果
id
没有设置,可能会导致数据重复插入,从而破坏数据的一致性。
2. GreenDAO 的注解处理器会生成哪些类及其作用
GreenDAO 的注解处理器会生成以下类:
DaoMaster
:管理数据库的创建和版本控制。包含DevOpenHelper
类,用于创建和管理数据库。DevOpenHelper
:继承自SQLiteOpenHelper
,用于创建和升级数据库。OpenHelper
:用于打开数据库连接。DaoMaster.OpenHelper
:用于打开数据库连接的辅助类。DaoMaster.DevOpenHelper
:用于开发环境中的数据库创建和升级。
DaoSession
:管理多个 DAO 的会话,提供对多个实体类的操作。DaoSession
:提供对多个 DAO 的访问,支持事务管理。
EntityDao
:每个实体类对应的 DAO 类,提供对该实体类的操作。UserDao
:例如,对于User
实体类,生成的 DAO 类是UserDao
,提供插入、查询、更新、删除等方法。
3. 补充和对比 CRUD 的几个方法
GreenDAO 提供了多种 CRUD 方法,每种方法有不同的用途和特点:
-
insert
:插入一条新的记录。javauserDao.insert(user);
-
insertInTx
:在一个事务中插入多条记录。javauserDao.insertInTx(users);
-
update
:更新一条记录。javauserDao.update(user);
-
updateInTx
:在一个事务中更新多条记录。javauserDao.updateInTx(users);
-
delete
:删除一条记录。javauserDao.delete(user);
-
deleteInTx
:在一个事务中删除多条记录。javauserDao.deleteInTx(users);
-
insertOrReplace
:插入一条记录,如果记录已存在则替换。javauserDao.insertOrReplace(user);
-
insertOrReplaceInTx
:在一个事务中插入或替换多条记录。javauserDao.insertOrReplaceInTx(users);
-
insertOrUpdate
:插入一条记录,如果记录已存在则更新。javauserDao.insertOrUpdate(user);
4. 详细解释一下关系映射的含义、使用、区别
GreenDAO 支持多种关系映射,包括一对一、一对多和多对多关系。
-
一对一关系:
-
含义:一个实体对象与另一个实体对象之间存在一对一的关系。
-
使用 :
java@Entity public class User { @Id private Long id; @Property private String name; @ToOne(joinProperty = "addressId") private Address address; @Property private Long addressId; // Getters and Setters } @Entity public class Address { @Id private Long id; @Property private String street; // Getters and Setters }
-
区别 :一对一关系通常使用
@ToOne
注解,通过joinProperty
指定外键。
-
-
一对多关系:
-
含义:一个实体对象与多个其他实体对象之间存在一对多的关系。
-
使用 :
java@Entity public class User { @Id private Long id; @Property private String name; @ToMany(referencedJoinProperty = "userId") private List<Note> notes; // Getters and Setters } @Entity public class Note { @Id private Long id; @Property private String content; @Property private Long userId; // Getters and Setters }
-
区别 :一对多关系通常使用
@ToMany
注解,通过referencedJoinProperty
指定外键。
-
-
多对多关系:
-
含义:多个实体对象与多个其他实体对象之间存在多对多的关系。
-
使用 :
java@Entity public class User { @Id private Long id; @Property private String name; @ToMany(joinProperties = { @JoinProperty(name = "userId", referencedName = "noteId") }) private List<Note> notes; // Getters and Setters } @Entity public class Note { @Id private Long id; @Property private String content; // Getters and Setters } @Entity public class UserNote { @Id private Long id; @Property private Long userId; @Property private Long noteId; // Getters and Setters }
-
区别 :多对多关系通常使用
@ToMany
注解,并通过joinProperties
指定中间表的外键。
-
5. 数据库迁移
假设一开始设置 id
自动增长,后来想改为在创建数据的时候自定义 id
。可以通过以下步骤进行数据库迁移:
-
修改实体类:
java@Entity public class User { @Id(autoincrement = false) private Long id; @Property private String name; @Property private String email; // Getters and Setters }
-
数据库迁移:
- 在
DevOpenHelper
的onUpgrade
方法中处理数据库迁移。 - 将现有的
id
字段从自动增长改为手动设置。
javapublic class MyApplication extends Application { private DaoMaster.DevOpenHelper helper; private DaoMaster daoMaster; private DaoSession daoSession; @Override public void onCreate() { super.onCreate(); helper = new DaoMaster.DevOpenHelper(this, "mydb.db", null) { @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // 迁移逻辑 if (oldVersion < 2) { // 将现有的 id 字段从自动增长改为手动设置 db.execSQL("ALTER TABLE USER RENAME TO USER_OLD"); db.execSQL("CREATE TABLE IF NOT EXISTS USER (" + "_id INTEGER PRIMARY KEY," + "name TEXT," + "email TEXT" + ")"); db.execSQL("INSERT INTO USER (_id, name, email) SELECT _id, name, email FROM USER_OLD"); db.execSQL("DROP TABLE USER_OLD"); } } }; daoMaster = new DaoMaster(helper.getWritableDatabase()); daoSession = daoMaster.newSession(); } public DaoSession getDaoSession() { return daoSession; } public DaoMaster getDaoMaster() { return daoMaster; } }
- 在
总结
GreenDAO 提供了一套完整的解决方案,帮助开发者在 Android 应用中高效地管理和操作 SQLite 数据库。通过定义实体类、生成 DAO 类、初始化数据库、插入、查询、更新、删除数据,以及支持关系映射和事务管理,GreenDAO 大大简化了数据库操作的复杂性。