1. GreenDao 3.0注解
- @Id :主键 long/Long型,可以通过@Id(autoincrement = true)设置自增长
- @Property:设置一个非默认关系映射所对应的列名,默认是的使用字段名 举例:@Property (nameInDb=”name”)
- @NotNul:设置数据库表当前列不能为空
- @Transient :添加次标记之后不会生成数据库表的列
1.)索引注解 - @Index:使用@Index作为一个属性来创建一个索引,通过name设置索引别名,也可以通过unique给索引添加约束
- @Unique:向数据库列添加了一个唯一的约束
2.)关系注解 - @ToOne:定义与另一个实体(一个实体对象)的关系
- @ToMany:定义与多个实体对象的关系
@ToOne的用法
customerId作为外键与Customer中的主键(也就是id)相连。
@Entity
public class Order {
@Id private Long id;
private long customerId;
@ToOne(joinProperty = "customerId")
private Customer customer;
}
@Entity
public class Customer {
@Id private Long id;
}
@ToMany的用法
第一种 Site类的ownerId作为外键,与User的主键相连。
@Entity
public class User {
@Id private Long id;
@ToMany(referencedJoinProperty = "ownerId")
private List<Site> ownedSites;
}
@Entity
public class Site {
@Id private Long id;
private long ownerId;
}
第二种 Site类的ownerId作为外键,与User的非主键不为空的键相连。
@Entity
public class User {
@Id private Long id;
@Unique private String authorTag;
@ToMany(joinProperties = {
@JoinProperty(name = "authorTag", referencedName = "ownerTag")
})
private List<Site> ownedSites;
}
@Entity
public class Site {
@Id private Long id;
@NotNull private String ownerTag;
}
@ToMany的属性referencedJoinProperty,类似于外键约束。
@JoinProperty 对于更复杂的关系,可以使用这个注解标明目标属性的源属性。
@JoinEntity 如果你在做多对多的关系,有其他的表或实体参与,可以给目标属性添加这个额外的注
@Entity
public class Site {
@Id private Long id;
@ToMany
@JoinEntity(
entity = JoinSiteToUser.class,
sourceProperty = "siteId",
targetProperty = "userId"
)
private List<User> authors;
}
@Entity
public class JoinSiteToUser {
@Id private Long id;
private Long siteId;
private Long userId;
}
@Entity
public class User {
@Id private Long id;
}
2. 条件查询方法
- “whereOr” where语句里面写的条件都是用“且”连接,whereOr里的语句使用“或”连接
- “distinct” 直接过滤掉重负字段
- “limit” 分页n个一页,一般和offset结合使用
- “offset” 忽略查询出的前n条结果
- “orderAsc” 以字段升序排序
- “orderDesc”以字段降序
- “preferLocalizedStringOrder” 本地化字符串排序
- “orderCustom” 自定义排序 里面需要传两个参数: 一个属性 和对应的排序方案 ASC 或是 DESC
- “orderRaw” 也是自定义排序, 把字段和 排序方案 写在一个字符串传入
- “stringOrderCollation” 也是自定义排序 可以合并多个升降排序方案 以日期升序 且 价格降序
- “notEq” 和eq相反,别傻傻在再去外面敲“!”取反
- “notIn” 同上
- “or” 或者
- “like” 就是sql语句的LIKE "%"+string+"%"
- “between” 也就是BETWEEN ? AND ? 可以取两个值的区间 (但是这条语句要慎用,不同的数据库不一样,有的是A<条件<B,有的是A<=条件<=B)
- “gt” 相当于 >
- “ge”相当于 >=
- “lt” 相当于 <
- “le”相当于 <=
- “isNull” 为空
- “notIsNull” 不为空
3. 缓存处理
出现的问题:
查询前后存入的3条不同记录,结果为3条相同的记录。
排查过程:
- 将Android手机上的数据库导出到电脑
- 使用SQLite查看工具发现数据库里的三条记录确实不相同
- 在GreenDao查询方法处打断点得到SQL语句
- 复制到SQLite查看工具中
- 运行语句得到的确实是3条不同的记录,这证明查询语句没有问题。
- 经排查发现,是GreenDao自带缓存导致的问题。
解决办法:
- 清除daoSession的缓存
daoSession.clear();
- 清除指定dao类的缓存
dao.detachAll();
何时清空缓存
在单纯的查询中我们没必要清理缓存,比如列表页查询集合,跳入详情页查询对象,这样的操作就没必要清理缓存,缓存会减少IO操作、大大提高我们的查询效率,但是执行了插入、修改、删除,会影响我们查时,我们只清理该表的缓存,一般情况就是我们在网络获数据后有必要对该表执行一下清理缓存。
4. 分页加载
分页加载20条数据,getTwentyRec(int offset)中控制页数offset++即可
public List<UserEntity> getTwentyRec(int offset){
UserDao dao = openReadableDb().getUserDao();
List<UserEntity> listMsg = dao.queryBuilder().offset(offset * 20).limit(20).list();
return listMsg;
}
5. insertOrReplace和save的区别
- insertOrReplace : 传入的对象在数据库中,有则更新无则插入。推荐同步数据库时使用该方法。
- save 类似于insertOrReplace,区别在于save会判断传入对象的key,有key的对象执行更新,无key的执行插入。当对象有key但并不在数据库时会执行失败.适用于保存本地列表
save源码如下
/**
* "Saves" an entity to the database: depending on the existence of the key property, it will be inserted
* (key is null) or updated (key is not null).
* <p>
* This is similar to {@link #insertOrReplace(Object)}, but may be more efficient, because if a key is present,
* it does not have to query if that key already exists.
*/
public void save(T entity) {
if (hasKey(entity)) {
update(entity);
} else {
insert(entity);
}
}
可以看出,save只判断了对象key是否存在,并不会去查询数据库。当对象有key但并不在数据库时,执行update语句不会有数据得到更新。
适用场景
只有本地数据库,且key默认由数据库生成。直接使用save就好。
插入的数据有key,其实这种情况通常是同步线上数据到本地数据库时的情况,因为直接使用了数据库的key,所以不能使用save,必须使用insertOrReplace。
结论
在确保插入数据有key时必须存在于数据库的情况下,适用save更高效。其他情况一律适用insertOrReplace