一、一对一关联
1、主键关联:两表共用同一ID
Example:每个人拥有一张身份证。
/**
* Person类(使用@PrimaryKeyJoinColumn注解主键关联)
*/
@Entity
public class Person {
private int id;
private String userId;
private String name;
private String email;
private IdentityCard identityCard;
@Id
//@GeneratedValue
public int getId() {
return id;
}
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@PrimaryKeyJoinColumn //这个注解只能写在生成ID的一端
public IdentityCard getIdentityCard() {
return identityCard;
}
//省略其它成员变量get/set方法...
}
/**
* 身份证类(使用@GenericGenerator配置ID生成器为foreign,并使用@GeneratedValue配置ID生成策略根据ID生成器生成)
*/
@Entity
public class IdentityCard {
private int id;
private String cardId;
private String name;
private Date birth;
private Person person;
@OneToOne(mappedBy="identityCard") //由mappedBy指定字段来维护双方间的关系,mappedBy只能放在非拥有的一方上注解。
public Person getPerson() {
return person;
}
@Id
@GenericGenerator(name ="pkGenerator",strategy="foreign" ,parameters={@Parameter(name="property",value="person")}) //配置Id生成器策略为foreign
//该表Id根据外表的Id赋值生成,Parameter中指定主表名。
@GeneratedValue(generator="pkGenerator") //配置Id生成策略
public int getId() {
return id;
}
@Temporal(TemporalType.DATE)
public Date getBirth() {
return birth;
}
//省略其它成员变量get/set方法...
}
@Test //测试类(双方的关系都要配置)
public void test() {
Person p = new Person();
p.setId(123);
p.setUserId("zhangsan");
p.setName("张三");
p.setEmail("54895646@qq.com");
IdentityCard card = new IdentityCard();
card.setCardId("35154578456554");
card.setName("张三");
p.setIdentityCard(card);
card.setPerson(p); //双方关系都要设置
}
2、外键关联
(1)单向外键关联
Example:每个人拥有一张身份证。
@Entity
public class Person { //人类
private int id;
private String userId;
private String name;
private String email;
private IdentityCard identityCard; //身份证外键
@Id
@GeneratedValue
public int getId() {
return id;
}
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name="identityCardId") //设置外键的列名
public IdentityCard getIdentityCard() {
return identityCard;
}
//省略其它成员变量get/set方法...
}
@Entity
public class IdentityCard { //身份证类
private int id;
private String cardId;
private String name;
private Date birth;
@Id
@GeneratedValue
public int getId() {
return id;
}
@Temporal(TemporalType.DATE) //设置日期类型:DATE/TIME/TIMESTAMP
public Date getBirth() {
return birth;
}
//省略其它成员变量get/set方法..
}
(2)双向外键关联
@Entity
public class Person { //人类
private int id;
private String userId;
private String name;
private String email;
private IdentityCard identityCard; //身份证外键
@Id
@GeneratedValue
public int getId() {
return id;
}
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name="identityCardId") //设置外键的列名
public IdentityCard getIdentityCard() {
return identityCard;
}
//省略其它成员变量get/set方法...
}
@Entity
public class IdentityCard { //身份证类
private int id;
private String cardId;
private String name;
private Date birth;
private Person person; //人员外键
@OneToOne(mappedBy="identityCard") //由mappedBy指定字段来维护双方间的关系,mappedBy只能放在非拥有的一方上注解。
public Person getPerson() {
return person;
}
@Id
@GeneratedValue
public int getId() {
return id;
}
@Temporal(TemporalType.TIMESTAMP)
public Date getBirth() {
return birth;
}
//省略其它成员变量get/set方法...
}
二、一对多关联
Example:一个帖子对应有多个评论,一个评论对应一个帖子
(1)单向
@Entity
public class Topic implements Serializable{ //帖子类
private int id;
private String title;
private Date createDate;
private String content;
private Set<Reply> replys = new HashSet<Reply>();
@Id
@GeneratedValue
public int getId() {
return id;
}
@OneToMany(targetEntity=Reply.class)
@JoinColumn(name="topicId") //不加该注解,则会生成Topic_Reply中间表。加上该注解则会在多方的表中生成一列"topicId"
public Set<Reply> getReplys() {
return replys;
}
//省略其它成员变量get/set方法...
}
@Entity
public class Reply implements Serializable{ //回复类
private int id;
private Date createDate;
private String content;
@Id
@GeneratedValue
public int getId() {
return id;
}
//省略其它成员变量get/set方法...
}
(2)双向
@Entity
public class Topic { //帖子类
private int id;
private String title;
private Date createDate;
private String content;
private Set<Reply> replys = new HashSet<Reply>();
@Id
@GeneratedValue
public int getId() {
return id;
}
@OneToMany(mappedBy="topic") //由mappedBy指定字段来维护双方间的关系,mappedBy只能放在非拥有的一方上注解,所以mappedBy应放在oneToMany上
public Set<Reply> getReplys() {
return replys;
}
//省略其它成员变量get/set方法...
}
@Entity
public class Reply { //回复类
private int id;
private Date createDate;
private String content;
private Topic topic; //帖子外键
@ManyToOne
@JoinColumn(name="topicId") //该字段指定多方关联一方的字段的名称,可不指定,因为mappedBy已经在多的一方自动生成外键了
public Topic getTopic() {
return topic;
}
@Id
@GeneratedValue
public int getId() {
return id;
}
//省略其它成员变量get/set方法...
}
三、多对一关联
(1)单向
@Entity
public class Topic implements Serializable{ //帖子类
private int id;
private String title;
private Date createDate;
private String content;
@Id
@GeneratedValue
public int getId() {
return id;
}
//省略其它成员变量get/set方法...
}
@Entity
public class Reply implements Serializable{ //回复类
private int id;
private Date createDate;
private String content;
private Topic topic; //帖子外键
@ManyToOne
@JoinColumn(name="topicId") //帖子外键在该表的列名
public Topic getTopic() {
return topic;
}
public void setTopic(Topic topic) {
this.topic = topic;
}
@Id
@GeneratedValue
public int getId() {
return id;
}
//省略其它成员变量get/set方法...
}
(2)双向
等同于一对多的双向关联。
四、多对多关联
Example:一个教师教多个学生,一个学生有多个教师。
(1)单向
@Entity
public class Teacher { //教师类
private int id;
private String name;
private int age;
private Set<Student> student = new HashSet<Student>();
@Id
@GeneratedValue
public int getId() {
return id;
}
@ManyToMany
@JoinTable(name="Teacher_Student", //两者之间关联的中间表的表名
joinColumns={
@JoinColumn(name="teacherId") //本表在中间表的外键名称
},
inverseJoinColumns={
@JoinColumn(name="studentId") //外表在中间表的外键名称
}
)
public Set<Student> getStudent() {
return student;
}
/**
* name:表字段名
* unique:值是否唯一
* nullable:值是否允许为空
* length:表字段长度
*/
@Column(name="name",unique=true,nullable = false,length = 30)
public String getName() {
return name;
}
//省略其它成员变量get/set方法...
}
@Entity
public class Student { //学生类
private int id;
private String name;
private Date birth;
private String sex;
@Id
@GeneratedValue
public int getId() {
return id;
}
//省略其它成员变量get/set方法...
}
(2)双向
@Entity
public class Teacher { //教师类
private int id;
private String name;
private int age;
private Set<Student> students = new HashSet<Student>(); //学生集合
@Id
@GeneratedValue
public int getId() {
return id;
}
@ManyToMany
@JoinTable(name="Teacher_Student", //两者之间关联的中间表的表名
joinColumns={
@JoinColumn(name="teacherId") //本表在中间表的外键名称
},
inverseJoinColumns={
@JoinColumn(name="studentId") //外表在中间表的外键名称
}
)
public Set<Student> getStudents() {
return students;
}
//省略其它成员变量get/set方法...
}
@Entity
public class Student { //学生类
private int id;
private String name;
private Date birth;
private String sex;
private Set<Teacher> teachers = new HashSet<Teacher>(); //教师集合
@Id
@GeneratedValue
public int getId() {
return id;
}
@ManyToMany(mappedBy="students")
public Set<Teacher> getTeachers() {
return teachers;
}
//省略其它成员变量get/set方法...
}
五、联合主键(不重要)
(1)使用@Embeddable注解
/**
* 主键类(注意:必须继承java.io.Serializable)
* 重写equals()、hascode()方法
*/
@Embeddable
public class UserPk implements Serializable{
private String userId;
private String role;
//省略其它成员变量get/set方法...
@Override
public boolean equals(Object o)
{
if(o instanceof UserPk)
{
UserPk pk= (UserPk)o;
if(this.userId.equals(pk.getUserId())&&this.role.equals(pk.getRole()))
return true;
}
return false;
}
public int hascode()
{
return this.role.hashCode();
}
}
/**
* 实体类(将主键类注解为该实体类Id)
*
*/
@Entity
@Table(name="Users")
public class User {
private UserPk userPk;
private String sex;
private String email;
@Id
public UserPk getUserPk() {
return userPk;
}
//省略其它成员变量get/set方法...
}
(2)使用@EmbeddedId注解
/**
* 主键类(注意:必须继承java.io.Serializable)
*
*/
public class UserPk implements Serializable{
private String userId;
private String role;
//省略其它成员变量get/set方法...
@Override
public boolean equals(Object o)
{
if(o instanceof UserPk)
{
UserPk pk= (UserPk)o;
if(this.userId.equals(pk.getUserId())&&this.role.equals(pk.getRole()))
return true;
}
return false;
}
public int hascode()
{
return this.role.hashCode();
}
}
/**
* 实体类(将主键类注解为EmbeddedId)
*
*/
@Entity
@Table(name="Users")
public class User {
private UserPk userPk;
private String sex;
private String email;
@EmbeddedId
public UserPk getUserPk() {
return userPk;
}
//省略其它成员变量get/set方法...
}
(3)使用@IdClass注解
/**
* 主键类(注意:必须继承java.io.Serializable)
*
*/
public class UserPk implements Serializable{
private String userId;
private String role;
//省略其它成员变量get/set方法...
}
/**
* 实体类(使用@IdClass注解该类,并将主键都注解为@Id)
*/
@Entity
@IdClass(UserPk.class)
@Table(name="Users")
public class User {
private String userId;
private String role;
private String sex;
private String email;
@Id
public String getUserId() {
return userId;
}
@Id
public String getRole() {
return role;
}
//省略其它成员变量get/set方法...
}
六、中间表多字段
Example:一个产品由多个部件组成,一个部件隶属于多个产品,number为产品对应的部件数量。
(1)单主键关联
@Entity
public class Product { //产品类
private int id;
private String pId;
private String pname;
private float price;
private Set<PartOfProduct> poc = new HashSet<PartOfProduct>();
@Id
@GeneratedValue
public int getId() {
return id;
}
@OneToMany(mappedBy="product")
public Set<PartOfProduct> getPoc() {
return poc;
}
//省略其它成员变量get/set方法...
}
@Entity
public class Component { //部件类
private int id;
private String cId;
private String cname;
private Set<PartOfProduct> pop = new HashSet<PartOfProduct>();
@Id
@GeneratedValue
public int getId() {
return id;
}
@OneToMany(mappedBy="component")
public Set<PartOfProduct> getPop() {
return pop;
}
//省略其它成员变量get/set方法...
}
@Entity
public class PartOfProduct { //中间表
private int id;
private Product product;
private Component component;
private float number;
private String memo;
@Id
@GeneratedValue
public int getId() {
return id;
}
@ManyToOne
@JoinColumn(name="productId") //设置外键列名
public Product getProduct() {
return product;
}
@ManyToOne
@JoinColumn(name="componentId") //设置外键列名
public Component getComponent() {
return component;
}
//省略其它成员变量get/set方法...
}
(2)多主键关联
@Entity
public class Product { //产品类
private int id;
private String pId;
private String pname;
private float price;
private Set<Component> components = new HashSet<Component>();
@Id
@GeneratedValue
public int getId() {
return id;
}
@ManyToMany
@JoinTable(name="PartsOfProduct",
joinColumns={@JoinColumn(name="productId")},
inverseJoinColumns={@JoinColumn(name="componentId")}
)
public Set<Component> getComponents() {
return components;
}
//省略其它成员变量get/set方法...
}
@Entity
public class Component {
private int id;
private String cId;
private String cname;
private Set<Product> products = new HashSet<Product>();
@Id
@GeneratedValue
public int getId() {
return id;
}
@ManyToMany(mappedBy="components")
public Set<Product> getProducts() {
return products;
}
//省略其它成员变量get/set方法...
}
@Entity
@IdClass(P_C_Pk.class)
public class PartOfProduct { //中间表类
private Product product;
private Component component;
@Id
public Product getProduct() {
return product;
}
@Id
public void setProduct(Product product) {
this.product = product;
}
//省略其它成员变量get/set方法...
}
public class P_C_Pk implements Serializable{ //主键类
private Product product;
private Component component;
@ManyToOne
@JoinColumn(name="productId")
public Product getProduct() {
return product;
}
@ManyToOne
@JoinColumn(name="componentId")
public Component getComponent() {
return component;
}
}