GitHub地址
greenDao的gradle配置
(1)progect gradle
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.3'
classpath 'org.greenrobot:greendao-gradle-plugin:3.2.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
(2)gradle中
apply plugin: 'com.android.application'
apply plugin: 'org.greenrobot.greendao'
android {
compileSdkVersion 23
buildToolsVersion "23.0.2"
greendao {
schemaVersion 2
targetGenDir 'src/main/java'
daoPackage 'com.lenovo.sharkchao.hospital.greendao'
}
defaultConfig {
applicationId "com.example.sharkchao.a"
minSdkVersion 8
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:23.0.1'
compile 'org.greenrobot:greendao:3.2.0'
compile 'com.android.support:design:23.0.1'
testCompile 'junit:junit:4.12'
}
一.@Entity:实体 在类中设置 可以创建与实体相关联的表
(1)schema = “myschema”, 当程序中有多个secema(数据库)时,可以选择我们想要的一个。
(2)active = true, 设置Entity是否是活动的。如果是活动的,那么他将有更新,删除,刷新的方法。
(3)nameInDb = “AWESOME_USERS”, 数据库中的表名,默认是实体类名。
(4)indexes = { @Index(value = “name DESC”, unique = trut) }, 索引
(5) createInDb = false, 是否会创建数据库表,默认是true 当多个实体映射一个表,或者表不在greenDao之内创建时为false。
(6)generateConstructors = true, 不管有没有有参函数,一个无参函数总是会创建
(7)generateGettersSetters = true 产生get,set方法。
(在成员变量前的注解)
(1)@Id(autoincrement = true) 主键自增长
(2)@NotNull 不为空
(3)@OrderBy(date desc) 降序
(4)@Transient 短暂的,不会持久化,因此不会生成数据库中的列
(5)@Property 参数,在数据库表中默认为如下格式customName—–CUSTOM_NAME
@Property(nameInDb = “USERNAME”) 固定格式如下
(6)@Unique private String name; 唯一约束
(7)Sqlite中主键必须是long类型,因此尽量添加一个附加属性
@Index(unique = true) Private String key;
(8)@ToOne:定义与另一个实体(一个实体对象)的关系(底下会有详解)
@ToMany:定义与多个实体对象的关系(底下会有详解)
二 查询表
List joes = userDao.queryBuilder()
.where(Properties.FirstName.eq("Joe"))
.orderAsc(Properties.LastName)
.list();
1)orderAsc:升序排序
(1)orderDesc: 降序排序
(1)eq():==
(1)noteq():!=
(1)gt(): >
(1)t():<
(1)ge:>=
(1)le:<=
(1)like():包含
(1)between:俩者之间
(1)in:在某个值内
(1)notIn:不在某个值内
三 关联关系
1:1 @ToOne(joinProperty = “userId”)
通过外键来关联另一个实体。使用到的两个对象类为:
(User,Picture)
具体实例
@Entity
public class User {
@Id
private Long UserId;
private long pictureId;
@Property(nameInDb = "NAME")
private String name;
@Property(nameInDb = "AGE")
private String age;
@Property(nameInDb = "SEX")
private String sex;
@ToOne(joinProperty = "pictureId")//pictureId是我们需要关联的外键
private Picture picture;
}
@Entity
public class Picture implements Serializable {
private static final long serialVersionUID = 11;
@Id
private Long pictureId;
private long userId;
@Property
private String pictureName;
@Property(nameInDb = "width")
private String width;
@Property(nameInDb = "height")
private String height;
@ToOne(joinProperty = "userId")
private User user;
}
需要注意的是:Intent传递对象需要用到:Serializable
必须把serialVersionUID 给带上,不然会报错。
1:n
@ToMany(referencedJoinProperty = "customerId")
joinProperties这个参数是referencedJoinProperty 参数的升级版
@ToMany(joinProperties = {
@JoinProperty(name = "id", referencedName = "customerId")
})
需要用到的两个实体类为:Customer .java 以及 Order.java
@Entity
public class Customer {
@Id
private Long id;
@Property
private String name;
// @ToMany(referencedJoinProperty = "customerId")
@ToMany(joinProperties = {@JoinProperty(name = "id", referencedName = "customerId")})
@OrderBy("date ASC")
private List<Order> orders;
}
@Entity
public class Order {
@Id
private Long id;
@Property
private Date date;
private long customerId;
}
@ToMany(referencedJoinProperty = “customerId”),注解写在对应关系的一里边。
它这个注解默认的是customer的主键对应order的外键。
当我们不需要用一的主键对应N的外键时,我们可以自己定制
即:
@ToMany(joinProperties = {@JoinProperty(name = "id", referencedName = "customerId")})
即本类中的id对应其他类中的customerId
M:n
@JoinEntity 定义了N:M的映射关系。 创建三个实体类,其中一个为关联类。 需
要的三个实体类分别为:Order.java。product.java。JoinProductsWithOrders.java
@Entity
public class Order {
@Id
private Long id;
@Property
private Date date;
private long customerId;
}
@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;
}
在类里边写toMany表示的是将此类当成唯一,他需要一个中间类生成的表来连接另外一个表(实体),
关键代码如下:
@ToMany
@JoinEntity(
entity = JoinProductsWithOrders.class,
sourceProperty = "productId",
targetProperty = "orderId"
)
private List<Order> ordersWithThisProduct;
查询数据
- 分页查询
limit(int): 限制查询的数量; offset(int): 每次返回的数量; offset不能单独使用; 查询与LazyList类
Query :
Query类表示一个查询能够执行很多次;而当通过QueryBuilder的任何查询方法(eg:list())来获取查询结果时,querybuilder都会
在其内部创建Query来执行查询语句的;如果执行多次查询应该使用Query对象; 如果只想获取一个结果时可以使用Query(or
QueryBuilder)中的unique()方法;LazyList : 可以通过以下方法获取查询结果集合;
list() 缓存查询结果;list()类型一般为ArrayList
listLazy() 懒查询,只有当调用list()中的实体对象时才会执行查询操作并且只缓存第一次被查询的结果,需要关闭
listlazyUncached() 懒查询,只有当调用list()中的实体对象时才会执行查询操作并且不缓存;
listIterator()
对查询结果进行遍历,不缓存,需要关闭;后面三个类是LazyList中的方法,LazyList为了执行不同的缓存策略其内部持有数据库的cursor对象;一般情况下这三个方法执行完毕后会自动关闭cursor;但是防止在还没有执行完查询结果时,对象被终结cursor还是无法被关闭的情况发生,需要手动关闭close();
插入数据(保存数据),以一对多为例
新建两个实体类,news.java comment.java 关系为1:n
Entity
public class News {
@Id
private Long id;
@Property
private String title;
@ToMany(joinProperties = {@JoinProperty(name = "id", referencedName = "newsId")})
@OrderBy("commentDate ASC")
private List<Comment> comment;
@Property
private String publishDate;
}
@Entity
public class Comment {
@Id
private Long id;
@Property
private String content;
@Property
private String commentDate;
private Long newsId;
}
/*** 保存新闻与评论数据,关系为1:n
*/
public void save(){
//新建一条新闻
News news1=new News();
news1.setPublishDate(new Date()+"");
news1.setTitle("这是第一条新闻");
NewsDao newsDao = GetDaoMaster.getDaoSession(BaseActivity.getCurrentActivity()).getNewsDao();
newsDao.insert(news1);
//新建两条评论
Comment comment1=new Comment(null,"好评!",new Date()+"",news1.getId());
Comment comment2=new Comment(null,"差评!",new Date()+"",news1.getId());
CommentDao commentDao = GetDaoMaster.getDaoSession(BaseActivity.getCurrentActivity()).getCommentDao();
commentDao.insert(comment1);
commentDao.insert(comment2);
//不需要提交吗????
news1.getComment().add(comment1);
news1.getComment().add(comment2);
news1.setCommentCount(2+"");
}
修改数据
public void update(){
//1.修改某个id的一条记录
NewsDao newsDao = GetDaoMaster.getDaoSession(BaseActivity.getCurrentActivity()).getNewsDao();
News news = newsDao.queryBuilder().where(NewsDao.Properties.Id.eq("1")).build().unique();
news.setTitle("修改之后的标题");
newsDao.update(news);
//2.修改符合某个约束条件的记录(修改title为"这是第一条新闻",commentcount>0的记录title字段为"今日iPhone6 Plus发布")
NewsDao newsDao1 = GetDaoMaster.getDaoSession(BaseActivity.getCurrentActivity()).getNewsDao();
QueryBuilder qb=newsDao1.queryBuilder();
qb.where(qb.and(NewsDao.Properties.Title.eq("这是第一条新闻"),NewsDao.Properties.CommentCount.gt("0")));
News news1 = (News) qb.build().unique();
news.setTitle("今日iPhone6 Plus发布");
newsDao.update(news);
//3.修改符合约束条件的记录(修改所有的title都为"今日iPhone6 Plus发布")
NewsDao newsDao2 = GetDaoMaster.getDaoSession(BaseActivity.getCurrentActivity()).getNewsDao();
QueryBuilder qb2=newsDao2.queryBuilder();
List<News>list = qb2.build().list();
for (News n:
list ) {
n.setTitle("今日iPhone6 Plus发布");
}
newsDao2.updateInTx(list);//updateAll()?
//4.将id=2的记录title修改为"今日iPhone6发布"
NewsDao newsDao3 = GetDaoMaster.getDaoSession(BaseActivity.getCurrentActivity()).getNewsDao();
News news3 = newsDao3.queryBuilder().where(NewsDao.Properties.Id.eq("2")).build().unique();
news.setTitle("今日iPhone6发布");
newsDao3.update(news);
//5.把news表中标题为“今日iPhone6发布”且评论数量大于0的所有新闻的标题改成“今日iPhone6 Plus发布”
NewsDao newsDao4 = GetDaoMaster.getDaoSession(BaseActivity.getCurrentActivity()).getNewsDao();
QueryBuilder qb4 = newsDao4.queryBuilder();
List<News>list4 = qb4.where(qb4.and(NewsDao.Properties.Title.eq("今日iPhone6发布"),NewsDao.Properties.CommentCount.gt("0"))).list();
for (News n:
list4 ) {
n.setTitle("今日iPhone6 Plus发布");
}
newsDao4.updateInTx(list);//updateAll()?
}
删除数据
public void delete() {
/*
* 1.删除id为2的记录
* 这不仅仅会将news表中id为2的记录删除,同时还会将其它表中以
* news id为2的这条记录作为外键的数据一起删除掉,因为外键既
* 然不存在了,那么这么数据也就没有保留的意义了
* */
NewsDao newsDao = GetDaoMaster.getDaoSession(BaseActivity.getCurrentActivity()).getNewsDao();
newsDao.deleteByKey(Long.getLong("2"));
//2.news表中标题为“今日iPhone6发布”且评论数等于0的所有新闻都删除掉
NewsDao newsDao2 = GetDaoMaster.getDaoSession(BaseActivity.getCurrentActivity()).getNewsDao();
QueryBuilder qb2 = newsDao2.queryBuilder();
List<News>list2 = qb2.where(qb2.and(NewsDao.Properties.Title.eq("今日iPhone6发布"),NewsDao.Properties.CommentCount.eq("0"))).list();
newsDao2.deleteInTx(list2);
//3.想把表中的所有news数据删除掉
NewsDao newsDao3 = GetDaoMaster.getDaoSession(BaseActivity.getCurrentActivity()).getNewsDao();
newsDao3.deleteAll();
//4通过对象也可以删除持久化的数据
NewsDao newsDao4 = GetDaoMaster.getDaoSession(BaseActivity.getCurrentActivity()).getNewsDao();
News news = newsDao4.queryBuilder().where(NewsDao.Properties.Id.eq("1")).build().unique();
news.delete();
}
查询数据
public void select() {
//-----------------------------------懒加载查询---------------------------------------------------
//1.查询news表中id为1的这条记录
NewsDao newsDao = GetDaoMaster.getDaoSession(BaseActivity.getCurrentActivity()).getNewsDao();
News news = newsDao.queryBuilder().where(NewsDao.Properties.Id.eq("1")).unique();
//2.获取news表中的第一条数据,最后一条数据
// News news1=newsDao.queryBuilder().list().get()
// News news2=newsDao.queryBuilder().offset();通过newsDao.count()方法
//3.news表中id为1、3、5、7的数据都查出来
//4.查询news表中所有评论数大于零的新闻
List<News> newsList4 = newsDao.queryBuilder().where(NewsDao.Properties.CommentCount.gt("0")).build().list();
//5.也许你并不需要那么多的数据,而是只要title和content这两列数据。那么也很简单,我们只要再增加一个连缀就行了
QueryBuilder<News>qb = newsDao.queryBuilder();
//6.将查询出的新闻按照发布的时间倒序排列,即最新发布的新闻放在最前面
List<News> newsList6 = newsDao.queryBuilder().orderDesc(NewsDao.Properties.PublishDate).build().list();
//7.也许你并不希望将所有条件匹配的结果一次性全部查询出来,因为这样数据量可能会有点太大了,而是希望只查询出前10条数据
List<News> newsList7 = newsDao.queryBuilder().orderDesc(NewsDao.Properties.PublishDate).limit(10).list();
//8.刚才我们查询到的是所有匹配条件的前10条新闻,那么现在我想对新闻进行分页展示,翻到第二页时,展示第11到第20条新闻
List<News> newsList8 = newsDao.queryBuilder().orderDesc(NewsDao.Properties.PublishDate).offset(10).limit(10).list();
//------------------------------------激进查询-----------------------------------------------------
//1.我们想要查询news表中id为1的新闻,并且把这条新闻所对应的评论也一起查询出来
News news11 = newsDao.queryBuilder().where(NewsDao.Properties.Id.eq("1")).unique();
List<Comment>list1 = news11.getComment();
CommentDao commentDao=GetDaoMaster.getDaoSession(BaseActivity.getCurrentActivity()).getCommentDao();
QueryBuilder<Comment>qb2 = commentDao.queryBuilder();
qb2.join(News.class,CommentDao.Properties.NewsId);
List<Comment>list2 = qb2.list();
//查询订单日期为++的素有客户
QueryBuilder<Customer> queryBuilder = getDaoSession(BaseActivity.getCurrentActivity()).getCustomerDao().queryBuilder();
queryBuilder.join(Order.class, OrderDao.Properties.CustomerId)
.where(OrderDao.Properties.Date.eq(new Date()));
List<Customer> order = queryBuilder.list();
for (int i = 0; i < order.size(); i++) {
System.out.println(order);
}
//当我需要姓名为++的订单的时候。
QueryBuilder<Order> queryBuilder2 = getDaoSession(BaseActivity.getCurrentActivity()).getOrderDao().queryBuilder();
queryBuilder2.join(Customer.class, CustomerDao.Properties.Id)//根据顾客的id链接
.where(CustomerDao.Properties.Name.eq("小明"));
List<Order> order2 = queryBuilder2.list();
//-----------------------------------原生查询-------------------------------------------------------
}
}