Xutils框架中关于DbUtils的使用
来源:互联网 发布:中国新歌声有网络直播 编辑:程序博客网 时间:2024/06/05 06:37
sqlite数据库与常见的mysql,orcale数据库大致无异,因为更加轻量级所以被Android和ios等web应用选作默认的数据库形式。
sqlite支持大部分的sql语言,android为我们提供了SQLiteDatabase这个类来进行sqlite数据库的操作,并且提供了一些相对简单的增删改查api(底层依旧是对sql语句的封装),但对于很多数据库基础薄弱的同学,尤其在java语境中,sql语句的拼装要加入各种转义符的情况下,一张表的复杂结构会对sqlite的使用产生畏惧感。所以,一些第三方的ORM(关系映射)开源框架就此诞生,如xutils中的DbUtils,GreenDao等。
ORM更加实际点解释其实就是直接将数据库中的数据转为java中的对象,让Android开发人员不在为复杂的sql查询,数据封装而生无可恋。
下面我们以Xutils快速开发框架中的DButils来对此类ORM框架进行一次简单的使用,其他ORM框架大同小异。
DButils使用注解的方式来更快的让开发人员来对表的结构进行建立,当然我们得首先有个数据库。
数据库的建立
public static DbUtils getDb(Activity activity) { if (db == null) { MyApplication application = (MyApplication) activity.getApplication(); db = DbUtils.create(activity, application.getPath(), "RunWold.db"); } return db; }这是开发者自己封装的单例类,DbUtils的核心类是DbUtils,执行DbUtils.create()方法后,当数据库已经存在,则直接返回此数据库对应的DbUtils,如果不存在则会去创建一个sqlite数据库,再返回DbUtils,注意数据库的创建需要读写权限。
当获得指定名字的DbUtils之后,我们就可以对此数据库进行数据库操作,首先我们需要建数据库表,而表结构在Android开发中大部分直接参照Bean结构来进行创建,DbUtils的注解形式可以让我们对Bean中的对象名,类名直接进行注解,然后调用save()方法就直接生成了与这个Bean相同结构的表,而通过查询方法之后,所返回直接就是这个Bean对象,这就是ORM的简便之处。
数据库表结构的建立
@Table(name = "cases") public static class DatasBean { @Column(column = "before") private String before; @Column(column = "after") private String after; @Id @NotNull private String casesId; @Column(column = "introduction") private String introduction; @Column(column = "createDate") private String createDate; @Transient private List<Integer> expertId; @Transient private List<String> name; @Transient private List<String> photo;我们在类名上面注明@Table注解并填写名称(当然后面还能添加更多的属性,如索引),这就表明这将在数据库中是一张表。
在变量上面定义@Column并填写名称,这就表明这是这张表的一个列,列的数据类型直接就是你定义的变量的数据类型,如Int string(text)等(当然,只能是基本数据类型)。
在casesId上面定义一个@Id标签,表明这是主键,主键应当保持唯一性,如果你的Bean结构中没有这种唯一性的数据,可以自己随意定义一个int类型的变量并赋予@Id的注解,这个@id的存在是必须的。
@Transient表示忽略,这个变量不参与表的结构,在这里,我们可以看到忽略的都是一些list集合,数据库是不支持数组的,这在下面我们会解决这个问题。
还有其他注解,包括主键的自增自减,各种约束类型等,在这里有更加详细的解释,其实也不多。
还有一个要注意的问题,这些你即将创建表的Bean必须含有空的构造函数,其他get()、set()方法与平常无异。
到了这里,我们对数据库结构进行了设计,其实这一部分一般都是数据库的重点操作需要很大一串的Sql语句,但是可以看到ORM框架直接方便了很多,那么下面我们就开始继续数据库的主要功能,增删改查。
当我们有了一个Bean的对象,也拥有了一个Dbutils对象之后,我们就可以对数据库进行操作了。
增
public void refreshDatas(List<MainBean.DataBean.DatasBean> datas) throws DbException { dbUtils.save(datas.get(0));//保存一个对象,但不会给主键赋值 dbUtils.saveAll(datas);//保存一个集合,但不会给主键赋值 dbUtils.saveBindingId(datas.get(0));//保存一个对象,会给你@Id的那个主键进行赋值 dbUtils.saveBindingIdAll(datas);//保存一个集合,会给你@id的那个主键进行赋值也就是casesID }
可以看到dbutils可以对数据集合一次性的进行的保存,当然保存的对象必须是你定义的表的那个对象,这里有两种情况一种是不给主键赋值,另一种反之,这里要注意,不给主键赋值就必须要求表中有一个自增或自检的主键(如上文提到的自定义的id变量),如果你的bean结构中有@id的属性,那么就选择saveBindId(),此时主键的值就是bean对象中的值(当然上文提过,@id的主键变量你必须确定是唯一的)
当调用save方法后如果不存在表则会先创建表然后再写入数据,如果存在表则会直接在表中写入数据,不需要单独调用cretable()方法。
删
public void refreshDatas(List<MainBean.DataBean.DatasBean> datas) throws DbException { dbUtils.delete(datas.get(0)); /** * 基于where条件的查询,第一个参数为你想要在那个表(也就是Bean)进行操作,第二个参数为where子语句 * where子语句在sql作为查询规范来应用,也就是你想要删除什么样的数据 * WhereBuilder.b()封装了where语句,第一个参数以什么列名进行对比,第二个是对比符号比如“=”、“<”、“>" * 第三个就是你拿来对比的值 这句话的意思就是删除一个casesId为2的列。 */ dbUtils.delete(MainBean.DataBean.DatasBean.class,WhereBuilder.b("casesId","=","2")); dbUtils.deleteById(MainBean.DataBean.DatasBean.class,datas.get(0).getCasesId()); dbUtils.deleteAll(MainBean.DataBean.DatasBean.class);
删操作同样很简便,基于对象的删除,直接删除这个对象所对应的数据库数据,基于where查询删除 ,删除一个集合或者整个表中的数据都删除。
改
dbUtils.update(datas.get(0),"before"); /** * 此语句同理 where为查询标准,也就是把casesid=2的这条数据中的befroe值 * 改为第一个参数对象中对应的变量值 */ dbUtils.update(datas.get(0),WhereBuilder.b("casesId","=","2"),"before"); dbUtils.updateAll(datas,"before");改同上
查
//查询该表所有数据 dbUtils.findAll(MainBean.DataBean.DatasBean.class); /** * 基于selector查询 select是sql语句中的查询语句 sql语句中的查询一般结构为select-from-where * 所以这里其实跟sql结构一样 from表示从什么表中查询 where为查询规范 * 这里就是从表中查出所有casesId为2的值(当然 因为casesId唯一性 只会有一条数据) */ dbUtils.findAll(Selector.from(MainBean.DataBean.DatasBean.class).where("casesId","=","2")); //查询一个主键值为2的列 dbUtils.findById(MainBean.DataBean.DatasBean.class,"2"); //查询此表中第一条数据 dbUtils.findFirst(MainBean.DataBean.DatasBean.class); //查询此表中符合条件的第一条数据 dbUtils.findFirst(Selector.from(MainBean.DataBean.DatasBean.class).where("casesId","=", "2"));
到这里,增删改查的基本操作已经讲解完毕,如果能熟练运用这些,一些简单的需求已经可以顺利完成,比如以userId为主键的头像保存,这样每次用户列表的头像就不需要频繁进行网络访问了,当用户通知头像改变后更新数据就可。
进阶
在上面的注解介绍中,我们忽略了一些List<String>集合,因为数据库是不支持数组保存的,那么如何解决这个问题?
其实方法有很多种,也是一般数据库操作人员保存数组的几种处理方式。
1.如果 泛型中是基本数据类型,如String,int可以使用字符串拼接,并用间隔号隔开。
2.如果泛型中是别的对象,可以序列化成json字符串进行保存。
3.使用关联表,这也是最正规也是最具Geek范儿的方式(虽然过程较为繁琐一点)。
在1,2两种方法中,我们需要修改bean的结构,比如当你List<String> photo和name<String> name被忽略,如果你想在表中存在这两个string类型的列,就得在bean中定两个string常量用来当作列名。
@Transient private List<String> name; @Transient private List<String> photo; @Column(column = "photo") private String photoDb; @Column(column = "photo") private String nameDb; /** * 手动设置的两个变量无法被fastJson或者Gson解析 所以当你获得数据之后 还需要在p层或者m层 * 手动调用这些set或者get方法 * 比如当你从数据库中取得一个本类对象之后 list<String> photo其实是空的 photoDb是有数据的 * 需要在数据处理层中将photoDb数据反序列化再设置到这个对象中 * @return */ public String getPhotoDb() { return photoDb; } /** * * @param photoDb 你在外部进行拼接或者序列化之后的string字符串 */ public void setPhotoDb(String photoDb) { this.photoDb = photoDb; } public String getNameDb() { return nameDb; }
拼接字符串或者序列化从过程到思想都是比较简单的,但总给人感觉一种不规范之感,所以我们运用数据库设计中的关联表的思想去处理这些数组数据。
所谓关联表就是一张表与另一张表存在着某种关联关系(废话),具体到这个案例就是,我们需要建立另外三张表,photo表,name表,expertId表,简单理解就是你忽略了多少list集合就有几张表(当然作为app的数据来说,不是每个变量都需要进行本地持久化),既然要建表我们就需要新建Bean,例如list<String> photo
@Table(name = "photo") public static class Photo { @Id @NotNull private int id; @Column(column = "casesId") private String casesId; @Column(column = "photo") private String photo; public Photo() { } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getPhoto() { return photo; } public void setPhoto(String photo) { this.photo = photo; } public String getCasesId() { return casesId; } public void setCasesId(String casesId) { this.casesId = casesId; } public String getPhtoto() { return photo; } public void setPhtoto(String photo) { this.photo = photo; } }
好了,在这个表中我们可以看到一个String类型的photo列 String类型casesId列 一个自定义的int id列,其中我们所谓的关联关系就是这个casesId,简单说来我们可以通过上一张表中的casesId查到这一层有关所有这个casesId的photo,而为什么我们不把casesId定为这个表的主键(@id)呢,因为这个表中的casesId会存在多个,一个photo就会有一个列,但这个列中casesId并不唯一。
当我们建立好这个表之后,我们还是在上一个Bean中写出调用DbUtils增删改查数据的方法。
public void setDbPhoto(DbUtils dbUtils) throws DbException { //遍历集合将数据保存在数据库 List<Photo> photos =new ArrayList<>(); for (String s : photo) { Photo photo = new Photo(); photo.setCasesId(casesId); photo.setPhtoto(s); photos.add(photo); } dbUtils.saveAll(photos); } public List<String> getDbPhoto(DbUtils dbUtils) throws DbException {List<DbModel> dbModelAll = dbUtils.findDbModelAll(Selector.from(Photo.class) .where("casesId", "=",casesId) .select("photo")); for (DbModel dbModel : dbModelAll) { String photoData = dbModel.getString("photo"); this.photo.add(photoData); } return photo; }; }
好了这就是关联表的设计,到这里Dbutils差不多基本讲解完毕,还有一些其他api比如判断表存不存在之类的,这里不做深入的介绍。
纵观整个DbUtils,包括同类型的GreenDao,其实在安卓中数据库的使用与其他平台中数据库应用并无二致,增删改查的api无非是为了简化数据库的操作难度,真正的数据库设计思想并不是一个框架就能提供的。
编程语言千变万化,唯有思想万古留存,GG。
- Xutils框架中关于DbUtils的使用
- xUtils中DbUtils的使用
- xutils中dbutils的基础使用详解
- xutils dbutils使用中遇到的问题
- xutils中dbutils的基础使用详解
- xUtils框架中关于注解的使用
- 关于XUtils的DBUtils使用遇到的错误
- xUtils插件的使用(dbUtils)
- Android Xutils框架使用之DBUtils
- xUtils框架—DbUtils
- xutils DbUtils框架
- xUtils框架之DbUtils
- Xutils 中 对数据库的操作 DButils
- xUtils 里的DbUtils使用心得
- xUtils中DbUtils用法
- DBUtils 框架的中batch批处理使用
- DBUtils框架的使用
- Android xUtils框架(一) DbUtils
- java同步方法和同步代码块
- 水仙花数
- [乐意黎转载]《一起学 Node.js》彻底重写完毕
- Java并发学习2--Sychronizer
- iOS开发之对日期格式处理的总结
- Xutils框架中关于DbUtils的使用
- 用户实际Ip获取
- win8 win10 安装msi 提示2502、2503的错误代码
- 构建高并发高可用的电商平台架构实践
- openmano使用
- html meta部分字段介绍
- 树莓派初次安装登陆无显示器SSH登陆被拒绝问题解决
- java Map及Map.Entry详解
- Unable to open connection to "Oracle, Microsoft provider V1.0.5000.0".