概述
传统关系型数据库定义了四种数据操作:
插入 Insert
删除 Delete
更新 Update
查询 Query
可以说,这四种操作涵盖了所有的数据操作。并且,除了 插入 操作,所有的操作都是可以一次针对多条记录的。
但是,Nutz.Dao 认为从使用者的角度来看,这四种操作还是有所不同的。比如,查询返回的结果,很多时候仅仅是一条记录。 我们需要为这种情况进行优化。所以,Nutz.Dao 在传统关系型数据库数据操作的基础上定义了如下的数据操作:
插入
Insert
一条 SQL 插入一条记录或者多条记录
插入
FastInsert
一条 SQL ,通过batch插入多条记录
删除
Delete
一条 SQL 删除一条记录
更新
Update
一条 SQL 更新一条或者多条记录
获取
Fetch
一条 SQL 获取一条记录
查询
Query
一条 SQL 根据条件获取多条记录
清除
Clear
一条 SQL 根据条件删除多条记录
建表
Create
根据实体建表
删表
Drop
根据实体/表名称进行删表
聚合
Func
执行sum,count等操作
请注意: 这里我是说 “一条” SQL。 如果通过 Dao 接口,你传入的是一个集合或者数组,它会为每一个元素 都生成一条 SQL 并执行,并更新操作:
Pet[] pets = xxxx; dao.update(pets);// 可以是数组,当然 pets 也可以是集合
同理,delete 和 insert 也支持传入数组和集合
示例的前提条件
我们假设已经创建了实体类 com.zzh.demo.Person 和实体表 t_person
在文档 Nutz.Dao 入门 中,我们已经声明了这个实体
下述所有的操作都是假设已经有了 dao 变量,并且它指向一个 Dao 的实例。文档 Nutz.Dao 入门 中,我们给出了如何创建 Dao 实例,以及如何搭建运行环境
创建数据表
为 Pet 创建数据表,如果数据表存在,先 DROP 掉,再创建
dao.create(Pet.class, true); //生产环境你可千万别这样写!!
为 Pet 创建数据表,如果数据表存在,忽略
dao.create(Pet.class, false); //一般我们都这样写
删除数据表
删除 Pet 的数据表
dao.drop(Pet.class);//全部删掉哦,没条件的,慎用!!
插入 Insert
Person p = new Person(); p.setName("Peter"); p.setAge(22); dao.insert(p); System.out.println(p.getId());
Person 对象的 Id 被自动更新了。
更多的关于 @Id 注解的描述,请参看 关于主键 以及 在插入前后的为字段设值
取得 Fetch
根据名称获取 (如果你的实体声明了 @Name 字段)
Person p = dao.fetch(Person.class,"Peter"); System.out.println(p.getId());
根据 ID 获取 (如果你的实体声明了 @Id 字段)
Person p = dao.fetch(Person.class,2); System.out.println(p.getName());
更新 Update
Person p = dao.fetch(Person.class,2); p.setAge(32); dao.update(p) dao.update(p, "^age$"); //仅更新age,参数是个正则表达式
更新多条
dao.update(Person.class, Chain.make("dead",true), Cnd.where("age",">",150));
删除 Delete
根据名称删除 (如果你的实体声明了 @Name 字段). 批量删除请用clear
dao.delete(Person.class,"Peter");
根据 ID 删除 (如果你的实体声明了 @Id 字段)
dao.delete(Person.class,2);
查询 Query
查询全部记录
List people = dao.query(Person.class, null);
按条件查询
List people = dao.query(Person.class, Cnd.where("name", "like", "P%"));
Cnd 类的全名是 org.nutz.dao.Cnd
它主要是用来快速替你建立一个 org.nutz.dao.Condition 接口的实现类
where() 函数 第一个参数是字段名,要和 Java 类里面的字段名相同。
where() 函数 第二个参数遵循 SQL 的标准,可以是 >, =, <= 等等
提供了一个 wrap 函数,你可以直接写 SQL 的条件
如果你愿意,你完全可以自己实现一个 Condition,来做更复杂灵活的判断
关于更多的查询条件的说明,请参看 复杂条件
分页查询
List people = dao.query(Person.class, Cnd.where("age", ">", 18), dao.createPager(2, 4));
dao.createPager 第一个参数是第几页,第二参数是一页有多少条记录
关于分页更多的说明,请参看 分页查询
清除 Clear
清除所有记录
dao.clear(Person.class); //还是那句,慎用
按条件清除
dao.clear(Person.class,Cnd.where("id", ">", 35));
关于更多的清除条件的说明,请参看 复杂条件
插入和更新集合
无论是插入 (Insert) 还是更新 (Update),你传入的对象都可以不仅仅是一个 POJO,你可以传入:
集合 ( Collection> )
Map,?>
数组 ( T[] )
Nutz.Dao 会自动替你拆包,对集合成员依次执行相应操作。 对于 Map,它会迭代每一个值。
集合操作(func)
整数类型. 例如调用sum
dao.func(Person.class, "sum", "age");
其他类型
dao.func2(Person.class, "min", "price");
自动建表
Dao接口有一个create方法,通过它可以让nutz为你建好数据库表
dao.create(Pet.class, false);
第一个参数是Pojo类, 第二个参数是如果表存在,是不是先删再重新建,否则就是保持原样
字段的详细定义,例如定义长度
@ColDefine(width=1024) private String data;
强制自定义字段类型
@ColDefine(customType="TEXT", type=ColType.VARCHAR) private String fu;
添加索引, 类级注解
@TableIndexes({@Index(name="orderid_userid", fields={"orderId", "userId"})}) public class UserOrder { private long id; private long orderId; private long userId; //... 其他属性 }
局限性
不生成外键
只能解决一般建表需求,复制的表结构请通过自定义sql完成
批量建表,扫描某个package下的bean,为带@Table注解的类建表
Daos.createTablesInPackage(dao, "net.wendal.nutzbook.bean", false);
表结构自动迁移
// 单个迁移 Daos.migration(dao, User.class, true, false, false); // 新增字段true,删除字段false,检查索引false // 批量迁移 Daos.migration(dao, "net.wendal.nutzbook.bean", true, false, false);