Top ↑
无匹配结果,请重新输入
一对一映射
Oct 30, 2017 5:03:26 PM

什么是一对一映射

有两张数据表,其中A表的某个字段的值指向B表的主键。因为A表的任何一条记录只能对应B表的一条且唯一一条记录,所以称这种 映射为A表对B表数据的一对一映射。(当然,反过来,你也可是说,是B表对A表的一对多映射)。

上述结构,如果用 POJO 来表示的话,可以参看下图:

如上图, Pet 中就可以有一个字段 master,通过自身的 masterId 指向一个 Master 对象,那么我们说 Pet.master 就是 Pet 对 Master 的一对一映射。

在 POJO 中配置一对一映射

在 POJO 类中字段中增加注解 @One

@Table("t_pet")
public class Pet extends Pojo {

    @Column
    public int masterId;

    @One(field = "masterId")
    // 1.r.59之前需要写target参数
    // @One(target = Master.class, field = "masterId")
    public Master master;

}

在 Pet 对象中必须存在一个 Master 类型的字段,你的一对一映射就需要配置在这个字段上。通过 @One 注解告诉 Nutz.Dao 对象 Pet 和 Master 对象的关系,其中:

  • 1.r.59之前你需要使用 target 表示你要映射的对象类型
  • field 表示你打算依靠本对象的哪一个字段来映射目标对象的主键

因此:

  • POJO 类中必须存在一个属性,本 POJO 将通过该属性同目标 POJO 类的主键 关联
  • 该属性必须同目标 POJO (Master)的主键类型相同
  • 注意,这里是大小写敏感的。

补充: 在一对一映射中,有可能会存在两边对应字段名称不同的情况,所以可以通过附加 key 来说明

     @Table("t_pet")
     public class Pet extends Pojo {

         @Column
         public int masterId;

         @One(field = "masterId", key = "id")
         // 1.r.59之前需要写target参数
         // @One(target = Master.class, field = "masterId", key = "id")
         public Master master;

     }

插入操作

如果你已经实现准备好了这样的对象:

Pet pet = new Pet();
pet.setName("XiaoBai");
Master master = new Master();
master.setName("Peter");
pet.setMaster(master);

那么你可以一次将 pet 以及它对应的 master 一起插入到数据表中

dao.insertWith(pet,"master");

Nutz.Dao 会根据正则表达式 "master" 寻找可以被匹配上的映射字段(只要声明了 @One, @Many, @ManyMany 任何一个注解,都是映射字段) 并根据注解具体的配置信息,执行相应的 SQL。比如上面的操作,会实际上:

执行 SQL : INSERT INTO t_master (name) VALUES("Peter");
执行 SQL 获取 最大值: SELECT MAX(id) FROM t_master  // 假设返回的值是 29
将该最大值 29 赋给 master 对象的主键 id
将该最大值 29 赋给 pet.masterId 字段
执行 SQL : INSERT INTO t_pet (name,masterId) VALUES("Xiaobai",29)

这里通过 SELECT MAX 来获取插入的最大值,是默认的做法,如果你想修改这个默认做法,请参看 关于主键一章。

  • 这里因为是一对一映射,所以会首先插入映射对象,以便用新的主键值更新主对象的映射字段
  • 如果你的对象中包括多个 @One 字段,被你的正则式匹配上,那么这些字段对应的字段(如果不为null)都会被匹配,并首先被插入

当然,你要想选择仅仅只插入映射字段的话,你可以:

dao.insertLinks(pet,"master");

那么上述操作实际上会执行:

执行 SQL : INSERT INTO t_master (name) VALUES("Peter");
执行 SQL 获取 最大值: SELECT MAX(id) FROM t_master  // 假设返回的值是 29
将该最大值 29 赋给 master 对象的主键 id

看,并不会插入 pet 对象。

获取操作

仅仅获取映射对象:

Pet pet = dao.fetch(Pet.class, "XiaoBai");
dao.fetchLinks(pet, "master");

这会执行操作:

执行 SQL: SELECT * FROM t_pet WHERE name='XiaoBai';  // 如果 pet.masterId 是 29
执行 SQL: SELECT * FROM t_master WHERE id=29;

但是 Nutz.Dao 没有提供一次获取 pet 对象以及 master 对象的方法,因为,你完全可以把上面的两句话写在一行上:

Pet pet = dao.fetchLinks(dao.fetch(Pet.class, "XiaoBai"), "master");

然后,你可以通过 pet.getMaster() 得到 Nutz.Dao 为 pet.master 字段设置的值。

更新操作

同时更新 pet 和 master

dao.updateWith(pet, "master");

这会执行

执行SQL: UPDATE t_master ....
执行SQL: UPDATE t_pet ...

仅仅更新 master

dao.updateLinks(pet, "master");

这会执行

执行SQL: UPDATE t_master ....

删除操作

同时删除 pet 和 master

dao.deleteWith(pet, "master");

仅仅删除 master

dao.deleteLinks(pet, "master");

清除 master

dao.clearLinks(pet, "master");

对于一对一映射来说其实清除和删除是等价的操作,对于一对多和多对多映射来说,就又区别了,因为清除只会执行一条 SQL 删除一批,而且删除会 逐个调用 dao.delete 来删除对象

本页面的文字允许在知识共享 署名-相同方式共享 3.0协议GNU自由文档许可证下修改和再使用。