Dao 接口的基本操作
概述
传统关系型数据库定义了四种数据操作:
- 插入 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<Person> people = dao.query(Person.class, null);
按条件查询
List<Person> 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<Person> 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);