Greendao2.2.3环境配置
//在根目录下的build.gradle file:
buildscript {
repositories {
jcenter()
mavenCentral() // add repository(有了jcenter可以不用配置mavenCentral)
}
greendao {
//数据库的schema版本,也可以理解为数据库版本号
schemaVersion 1
//设置DaoMaster、DaoSession、Dao包名,也就是要放置这些类的包的全路径。
daoPackage 'com.zhxy.www.test.greendao'
//设置DaoMaster、DaoSession、Dao目录
targetGenDir 'src/main/java'
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.0'
classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' // add plugin
}
}
// 在项目中的build.gradle file:
apply plugin: 'com.android.application'
apply plugin: 'org.greenrobot.greendao' // apply plugin
dependencies {
compile 'org.greenrobot:greendao:3.2.2' // add library
}
Make project 一下让android studio下载相应的工具
然后再bean包下创建一个实体如people
然后make project一下自动生成的代码就出来了 ,可以在项目中自由使用
greendao中有三个基本的接口,分别是DaoMaster,DaoSession,Daos;
DaoMaster是greendao的入口,持有SQliteDataBase对象,被用于管理DAO类。它有静态的方法用于创建表和删除表,内部类为openHelper和DevOpenHelper
DaoSession管理着所有的可用的DAO对象,这些对象可以使用getter方法来获取。DaoSession针对实体提供一些普通的持久化方法,如insert,load,refresh,delete。另外DAOSession对象还可以用来标示追踪作用域
DAOS:数据访问对象用于持久化和查询实体。greendao为每一个实体生成一个DAO类,它持有的持久化方法比DAOSession多很多。
greendao的初始化为
4 5 6 7 | // do this once, for example in your Application class helper = new DaoMaster.DevOpenHelper(this, "notes-db", null); db = helper.getWritableDatabase();//db是DataBase daoMaster = new DaoMaster(db); daoSession = daoMaster.newSession(); // do this in your activities/fragments to get hold of a DAO noteDao = daoSession.getNoteDao(); |
Greendao 3及以上使用注解来定义实体
5 6 7 8 9 10 11 12 13 14 15 16 | @Entity public class User { @Id(autoincrement = true) private Long id;
@Property(nameInDb = "USERNAME") private String name;
@NotNull private int repos;
@Transient private int tempUsageCount;
... } |
@entity注释将Java类用户转化为一个数据库支持的实体。这还将指导greenDAO生成必要的代码(例如DAOs),它只支持Java类。如果你喜欢像Kotlin这样的另一种语言,你的实体类仍然必须是Java。虽然没有任何附加参数通常是可以的,但是您仍然可以使用@entity来配置一些细节:注意,在使用分级插件时,当前不支持多个模式。目前,继续使用您的生成器项目。
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 | @Entity( 、//如果您有多个模式,您可以告诉greenDAO一个实体属于哪个模式(选择任何字符串作为名称) schema = "myschema",
//标记使实体“活动”:活动实体具有更新、删除和刷新方法 active = true,
//在默认情况下,指定数据库中表的名称,名称基于实体类名 nameInDb = "AWESOME_USERS",
//定义跨越多个列的索引 indexes = { @Index(value = "name DESC", unique = true) },
//如果DAO创建数据库表(默认为true),则标记为true。如果将多个实体映射到一个表,或者表创建在greenDAO之外完成,那么将其设置为false createInDb = false,
//是否应该生成一个所有的属性构造函数,总是需要一个无args构造函数 generateConstructors = true,
// 是否缺失都应该生成属性的getter和setter generateGettersSetters = true ) public class User { . |
@property允许您定义一个非默认的列名称,该属性被映射到。如果没有,greenDAO将以sql式的方式使用字段名
@notnull使该属性在数据库端成为“非空”列。通常,用@notnull标记简单类型(long, int, short, byte),同时使用包装类((Long, Integer, Short, Byte)为可空值。
@Transient 让properties 被排除在持久性之外。使用这些临时状态,也可以使用来自Java的Transient 关键字
1 2 3 4 5 | @Id private Long id; @Index(unique = true) private String key; |
在属性中使用@index为相应的数据库列创建一个数据库索引。使用以下参数自定义
建立索引的目的是加快对表中记录的查找或排序。为表设置索引要付出代价的:一是增加了数据库的存储空间,二是在插入和修改数据时要花费较多的时间(因为索引也要随之变动)。数据库索引就是为了提高表的搜索效率而对某些字段中的值建立的目录 。
创建索引可以大大提高系统的性能。第一,通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。第二,可以大大加快数据的检索速度,这也是创建索引的最主要的原因。第三,可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。第四,在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。第五,通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。
因为,增加索引也有许多不利的方面。第一,创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。第二,索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。第三,当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度
name: 如果您不喜欢greenDAO为该索引生成的默认名称,您可以在这里指定您的名称。
unique:向索引添加一个惟一的约束,强制所有的值都是惟一的。
Relations
数据库表可以使用1:1、1:N或N:M关系相互关联。如果您是数据库关系的新手,那么在讨论ORM细节之前,最好先了解一下。这里有一些随机的链接,讨论一般的关系。在greenDAO中,实体涉及到使用到一个或多个关系。例如,如果你想在greenDAO中建立一个1:n关系,你将会有-To-One对一个和一个-To-Many的关系。但是,请注意,-To-One和-To-Many关系并没有与每个o联系起来
To-One Relations
@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;
}
@ToOne注释定义了与另一个实体(一个实体对象)的关系。将其应用于持有其他实体对象的属性
greenDao内部需要一个指向目标表的ID的字段,使用joinProperty 参数来指定,如果目标表格没有这个字段,那么将自动创建一个字段去保存这个键
3 4 5 6 7 8 9 10 11 12 13 14 | @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; } |
to-one 关系的getter方法(这个例子中的getCustomer)会在第一次调用的时候延迟解析目标实体,随后立即返回刚才解析的对象,
注意,如果你改变它的外键(这里的customerId),下一次调用getter方法(getCustomer())会解析已更新ID的实体。如果你设置了一个新的实体(setCustomer())那么外键也会相应更新(customerId)
Customer customerA = user.getCustomer();
聽
// change the customer id
user.setCustomerId(customerIdB);
// or set a customer with a different id
user.setCustomer(customerB);
聽
customerB = user.getCustomer();
assert(customerA.getId() != customerB.getId());
注意:如果想要急切的加载one-relation关系则使用Dao类中的loadDeep() 和 queryDeep() ,这两个方法会使用一个简单的数据库query来解析带one-relation,如果一直访问的是相关实体,这将对性能好
To-Many Relations
@ToMany 定义了一个其他实体的对象集合,这些实体以list形式来展示,被引用的实体有一个或者多个标注@ToMany 注解的字段
@ToMany 有三种参数映射方式,只能用其中一种
referencedJoinProperty:指向目标id所在的实体的外键的name值
4 5 6 7 8 9 10 11 12 13 14 15 | @Entity public class Customer { @Id private Long id;
@ToMany(referencedJoinProperty = "customerId") @OrderBy("date ASC") private List<Order> orders; }
@Entity public class Order { @Id private Long id; private Date date; private long customerId; } |
@joinProperties :对于更加复杂的关系,可以使用此注解。每一个@joinProperties都需要一个本实体的字段和目标实体的一个字段。
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | @Entity public class Customer { @Id private Long id; @Unique private String tag;
@ToMany(joinProperties = { @JoinProperty(name = "tag", referencedName = "customerTag") }) @OrderBy("date ASC") private List<Site> orders; }
@Entity public class Order { @Id private Long id; private Date date; @NotNull private String customerTag; } |
@JoinEntity 如果你正在执行一个连接实体(表格)的多对多的关系,那么这个注解会放在你的字段上
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | @Entity public class Product { @Id private Long id;
@ToMany @JoinEntity( entity = JoinProductsWithOrders.class, sourceProperty = "productId", targetProperty = "orderId" ) private List<Order> ordersWithThisProduct; }
@Entity public class JoinProductsWithOrders { @Id private Long id; private Long productId; private Long orderId; }
@Entity public class Order { @Id private Long id; } |
一旦运行起来,插件就会自动生成一个getter来解析被引用实体的list列表,就像上面两种情况一样
List<Order> orders = customer.getOrders();
Resolving and Updating To-Many Relations
To-many关系在第一次调用的时候被延迟解析,然后被缓存保存在一个list中源实体中。依次接下来调用gettter方法时候不会查询数据库
更新to-many关系需要一些额外的操作,因为to-many中的list被缓存了,因材当把相关实体添加到数据库的时候不会产生更新,如下
// get the current list of orders for a customer
List<Order> orders1 = customer.getOrders();
聽
// insert a new order for this customer
Order order = new Order();
order.setCustomerId(customer.getId());
daoSession.insert(order);
聽
// get the list of orders again
List<Order> orders2 = customer.getOrders();
聽
// the (cached) list of orders was not updated
// orders1 has the same size as orders2
assert(orders1.size() == orders2.size);
// orders1 is the same object as orders2
assert(orders1.equals(orders2));
因此,要添加新的相关实体,请手动将它们添加到源实体的to-many 的list中:
1 2 3 4 5 6 7 8 9 10 11 | // get the to-many list before inserting the new entity // otherwise the new entity might be in the list twice List<Order> orders = customer.getOrders(); // create the new entity Order newOrder = ... // set the foreign key property newOrder.setCustomerId(customer.getId()); // persist the new entity daoSession.insert(newOrder); // add it to the to-many list orders.add(newOrder); |
同样的,你也可以删除相关的实体
3 4 5 | List<Order> orders = customer.getOrders(); // remove one of the orders from the database daoSession.delete(someOrder); // manually remove it from the to-many list orders.remove(someOrder); |
当添加、更新或删除许多相关的实体时,您可以使用重置方法来清除缓存列表。下一个得到的是相关的实体:
2 3 | // clear any cached list of related orders customer.resetOrders(); List<Order> orders = customer.getOrders(); |
双向1对多关系(1:n)
有时你想在两个方向上导航1:N个关系。在greenDAO,你必须添加一个到to-one和一个to-many的关系来实现这个
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | @Entity public class Customer { @Id private Long id;
@ToMany(referencedJoinProperty = "customerId") @OrderBy("date ASC") private List<Order> orders; }
@Entity public class Order { @Id private Long id; private Date date; private long customerId;
@ToOne(joinProperty = "customerId") private Customer customer; } |
利用这种关系,我们可以得到他们所有的关系
|
Tree Relations
您可以通过对一个实体进行建模来对树关系进行建模,这个实体具有一个to-one和一个指向自身的to-many关系:
3 4 5 6 7 8 9 10 11 12 | @Entity public class TreeNode { @Id private Long id;
private Long parentId;
@ToOne(joinProperty = "parentId") private TreeNode parent;
@ToMany(referencedJoinProperty = "parentId") private List<TreeNode> children; } |
生成的实体可以让您导航它的父和子
| TreeNode parent = entity.getParent(); List<TreeNode> children = entity.getChildren(); |