Hibernate 关联关系

来源:互联网 发布:mac不能上网 编辑:程序博客网 时间:2024/05/29 10:02

用 Annotation 讲解


一、一对一单向外键关联

一对一关联的注解是 @OneToOne,同时我们还可以在 @OneToOne 注解下面指定 @JoinColumn(name="xx") 来指定外键的名称:

   1:  @OneToOne
   2:  @JoinColumn(name="fk")
   3:  private Husband husband;
.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }

可以通过下面的语句来查看 SQL 语句:

   1:  new SchemaExport(new Configuration().configure()).create(true,true);
.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }

二、一对一双向外键关联

一对一双向外键关联还是使用 @OneToOne 注解,需要在双向关联的一方为 @OneToOne 指定属性 mappedBy="xx":

Husband.java:

   1:  @OneToOne
   2:  private Wife wife;

Wife.java:

   1:  @OneToOne(mappedBy="wife")
   2:  private Husband husband;
.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }

三、一对一单向主键关联

一对一单向主键关联使用 @OneToOne 注解,并且在此注解下加 @PrimaryKeyJoinColumn 即可:

   1:  @OneToOne
   2:  @PrimaryKeyJoinColumn
   3:  private Husband husband;
.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }

四、一对一双向主键关联

在双向关联的双方声明 @OneToOne 和 @PrimaryKeyJoinColumn 注解即可:

Wife.java:

   1:  @OneToOne
   2:  @PrimaryKeyJoinColumn
   3:  private Husband husband;
.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }

Husband.java:

   1:  @OneToOne
   2:  @PrimaryKeyJoinColumn
   3:  private Wife wife;
.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }

五、一对一单向联合主键关联

联合主键,这需要单独创建一个主键类 WifePk.java,内容如下:

   1:  public class WifePk implements Serializable{
   2:      private int id;
   3:      private String name;
   4:  //Getters,setters,equals and hashCode methods omitted here...
   5:  }
.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }

在 Wife.java 中使用联合主键:

   1:  @Entity
   2:  @IdClass(value=WifePk.class)
   3:  public class Wife {
   4:      @Id
   5:      private int id;
   6:      @Id
   7:      private String name;
   8:      private double salary;
   9:  //Codes omitted here...
  10:  }
.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }

在 Husband.java 中使用 Wife 关联:

   1:  @Entity
   2:  public class Husband {
   3:      @Id
   4:      private int id;
   5:      private String name;
   6:      private double salary;
   7:      @OneToOne
   8:      @JoinColumns({ 
   9:              @JoinColumn(name = "WifeId", referencedColumnName = "id"),
  10:              @JoinColumn(name = "WifeName", referencedColumnName = "name") 
  11:              })
  12:      private Wife wife;
  13:  //Codes omitted here...
  14:  }
@JoinColumns 注解的作用是指定生成的外键的名称的,参数是 @JoinColumn 数组。省去不写则会由 hibernate 自动生成外键名称。

六、组件映射

主键映射意思是把一个对象当做另一个对象的一部分存在同一张表中,就像联合主键一样,但是不是作为主键而已。比方说 Wife 是 Husband 的一部分,需要映射在同一张表中,需要这样做:

Wife.java 不需要独立映射成为一张表,所有不需要 @Entity 注解和 @Id 注解了,而且,因为 Wife  和 Husband 会被映射到同一张表中,所以两个类中不能出现相同的字段,Wife 也不再需要主键 Id 字段了:

Wife.java:

   1:  public class Wife {
   2:      private String wifeName;
   3:      private double wifeSalary;
   4:  //Getters and setters omitted here...
   5:  }
.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }

在 Husband.java 中需要使用 @Embedded 注解说明 Wife 是作为一个组件映射的:

   1:  @Entity
   2:  public class Husband {
   3:      @Id
   4:      private int id;
   5:      private String name;
   6:      private double salary;
   7:      @Embedded
   8:      private Wife wife;
   9:  //Getters and setters omitted here...
  10:  }
.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }

七、多对一单向关联

以 Group 和 User 类为例,一个 Group 可以有多个 User ,而一个 User 只能属于一个 Group ,是典型的多对一关联。多对一使用的是 @ManyToOne 注解:

Group.java:

   1:  @Entity
   2:  @Table(name="mygroup")
   3:  public class Group {
   4:      @Id
   5:      @GeneratedValue
   6:      private int id;
   7:      private String name;
   8:  //Getters and setters omitted here...
   9:  }

因为 group 是 MySQL 的关键字,所以使用 @Table 注解更改表名为 mygroup。

User.java:

   1:  @Entity
   2:  public class User {
   3:      @Id
   4:      @GeneratedValue
   5:      private int id;
   6:      private String name;
   7:      @ManyToOne
   8:      private Group group;
   9:  //Setters and getters omitted here...
  10:  }
.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }

因为每个 User 只属于一个 Group ,所以在 User 中定义一个 Group 域,并使用 @ManyToOne 注解。


八、一对多单向关联

还是以 Group 和 User 为例,现在是 Group 里面有多个 User:

Group.java:

   1:  @Entity
   2:  @Table(name="mygroup")
   3:  public class Group {
   4:      @Id
   5:      @GeneratedValue
   6:      private int id;
   7:      private String name;
   8:      @OneToMany
   9:      @JoinColumn(name="GroupId")
  10:      private Set users = new HashSet();
  11:  //Getters and setters omitted here...
  12:  }

如果不加注 @JoinColumn 注解,Hibernate 会生成三张表,也就是单做多对多处理。所以加注 @JoinColumn 注解是必要的。

User.java:

   1:  @Entity
   2:  public class User {
   3:      @Id
   4:      @GeneratedValue
   5:      private int id;
   6:      private String name;
   7:  //Getters and setters omitted here...
   8:  }
.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }

九、一对多(多对一)双向关联

只要是双向关联就一定要加 mappedBy 属性:

Group.java:

   1:  @Entity
   2:  @Table(name="mygroup")
   3:  public class Group {
   4:      @Id
   5:      @GeneratedValue
   6:      private int id;
   7:      private String name;
   8:      @OneToMany(mappedBy="group")
   9:      private Set users = new HashSet();
  10:  //Getters and setters omitted here...
  11:  }
.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }

User.java:

   1:  @Entity
   2:  public class User {
   3:      @Id
   4:      @GeneratedValue
   5:      private int id;
   6:      private String name;
   7:      @ManyToOne
   8:      private Group group;
   9:  //Getters and setters omitted here...
  10:  }
.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }

mappedBy 属性之所以要加在 Group.java 中,因为这符合数据库表设计原则,而且在 @ManyToOne 注解中还没有 mappedBy 属性。


十、多对多单向关联

多对多关联就像一个 Teacher 会有多个 Student,而一个 Student 也可以被多个 Teacher 教,符合多对多关联:

Teacher.java:

   1:  @Entity
   2:  public class Teacher {
   3:      @Id
   4:      private int id;
   5:      private String name;
   6:      @ManyToMany
   7:      @JoinTable(name="s_t_table",
   8:              joinColumns={@JoinColumn(name="t_id")},
   9:              inverseJoinColumns={@JoinColumn(name="s_id")}
  10:      )
  11:      private Set students = new HashSet();
  12:  //Getters and setters omitted here...
  13:  }
.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }

@JoinTable 是用于指定生成的第三方表的名称以及里面对应的字段的名称,joinColumns 属性定义的是本类的主键在第三方表的字段名称,inverseJoinColumns 属性定义的是另一个类中的主键在第三方表中对应的名称。可以省去 @JoinTable 注解使用 HIbernate 自动生成的表名和字段名。

Student.java:

   1:  @Entity
   2:  public class Student {
   3:      @Id
   4:      private int id;
   5:      private String name;
   6:  //Getters and setters omitted here...
   7:  }
.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }

十一、多对多双向关联

又是双向关联,所以一定要记得 mappedBy 属性:

Teacher.java:

沿用多对多单向关联的 Teacher.java。

Student.java:

   1:  @Entity
   2:  public class Student {
   3:      @Id
   4:      private int id;
   5:      private String name;
   6:      @ManyToMany(mappedBy="students")
   7:      private Set teachers = new HashSet();
   8:  //Getters and setters omitted here...
   9:  }
.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }