hibernate关联映射注解

hibernate的关联映射

无连接表的N-1关联

使用@JoinColumn来修饰代表关联实体的属性。映射底层的外键列。
person->Address(n-1)

@Entity
@Table(name="person_inf")
public class Person
{
 ....
  @ManyToOne(targetEntity=Address.class)
  @JoinColumn(name="address_id" , nullable=false)
  @Cascade(CascadeType.ALL)
  private Address address;

有连接表的N-1关联

使用@JoinTable映射底层连接表的 信息

@ManyToOne(targetEntity=Address.class)
  @JoinTable(name="person_address", 
    joinColumns=@JoinColumn(name="person_id"
      , referencedColumnName="person_id", unique=true),
    inverseJoinColumns=@JoinColumn(name="address_id"
      , referencedColumnName="address_id")
  )
  private Address address;

单向1-1

使用@OnetoOne and @JoinColumn并指定unique=true

@OneToOne(targetEntity=Address.class)
  @JoinColumn(name="address_id"
    , referencedColumnName="address_id" , unique=true)
  private Address address;

有连接表的单向1-1

这种情况很少见,但是hibernate还是提供了支持。只要在相应的@inverseJoinColumn属性映射的外键列增加unique=true即可

@OneToOne(targetEntity=Address.class)
  @JoinTable(name="person_address",
    joinColumns=@JoinColumn(name="person_id"
      , referencedColumnName="person_id" , unique=true),
    inverseJoinColumns=@JoinColumn(name="address_id"
      , referencedColumnName="address_id", unique=true)
  )
  private Address address;

无连接表的单向1-N关联

在1的一端使用JoinColumn修饰集合Set属性,映射外键列即可。

@OneToMany(targetEntity=Address.class)
  @JoinColumn(name="person_id" , referencedColumnName="person_id")
  private Set<Address> addresses
    = new HashSet<>();

有连接表的单向1-N

@OneToMany(targetEntity=Address.class)
  @JoinTable(name="person_address",
    joinColumns=@JoinColumn(name="person_id"
      , referencedColumnName="person_id"),
    inverseJoinColumns=@JoinColumn(name="address_id"
      , referencedColumnName="address_id", unique=true)
  )
  private Set<Address> addresses
    = new HashSet<>();

单向的N-N

使用@ManyToMany @JoinTable来映射连接表。并且去掉@inverseJoinColumns属性所指定的@JoinColumn中的unique=true

@ManyToMany(targetEntity=Address.class)
  @JoinTable(name="person_address",
    joinColumns=@JoinColumn(name="person_id"
      , referencedColumnName="person_id"),
    inverseJoinColumns=@JoinColumn(name="address_id"
      , referencedColumnName="address_id")
  )
  private Set<Address> addresses
    = new HashSet<>();

双向1-N关联

推荐使用双向1-N关联。并且让N的一端控制关联关系。
无连接表的双向1-n关联。
N的一端:@OneToMany(mappedBy=”“)
1的一端:@ManyToOne @JoinColumn来映射外键列。

@Entity
@Table(name="person_inf")
public class Person
{
....
  @OneToMany(targetEntity=Address.class
    , mappedBy="person")
  private Set<Address> addresses
    = new HashSet<>();
}
 @Entity
@Table(name="address_inf")
public class Address
{

  ...
  @ManyToOne(targetEntity=Person.class)
  @JoinColumn(name="person_id" , referencedColumnName="person_id"
    , nullable=false)
  private Person person;
}

有连接表的双向1-N关联
1的一端无需改变
N的一端@JoinTable指定连接表

 @OneToMany(targetEntity=Address.class
    , mappedBy="person")
  private Set<Address> addresses
    = new HashSet<>();

@ManyToOne(targetEntity=Person.class)
  @JoinTable(name="person_address",
    joinColumns=@JoinColumn(name="address_id"
      , referencedColumnName="address_id", unique=true),
    inverseJoinColumns=@JoinColumn(name="person_id"
      , referencedColumnName="person_id")
  )
  private Person person;
}

双向N-N关联

双方都是用@ManyToMany @JoinTable属性

  @ManyToMany(targetEntity=Person.class)
  @JoinTable(name="person_address",
    joinColumns=@JoinColumn(name="address_id"
    inverseJoinColumns=@JoinColumn(name="person_id"
      , referencedColumnName="person_id")
  )
  private Set<Person> persons
    = new HashSet<>();

@ManyToMany(targetEntity=Address.class)
  @JoinTable(name="person_address",
    joinColumns=@JoinColumn(name="person_id"
    inverseJoinColumns=@JoinColumn(name="address_id"
      , referencedColumnName="address_id")
  )
  private Set<Address> addresses
    = new HashSet<>();

双向1-1关联

  1. 基于外键
@OneToOne(targetEntity=Address.class , mappedBy="person")
  private Address address;

@OneToOne(targetEntity=Person.class)
  @JoinColumn(name="person_id" , referencedColumnName="person_id"
    , unique=true)
  private Person person;
  1. 有连接表
    不推荐使用
  @OneToOne(targetEntity=Address.class)
  @JoinTable(name="person_address",
    joinColumns=@JoinColumn(name="person_id"
      , referencedColumnName="person_id" , unique=true),
    inverseJoinColumns=@JoinColumn(name="address_id"
      , referencedColumnName="address_id", unique=true)
  )
  private Address address;

    @OneToOne(targetEntity=Person.class)
  @JoinTable(name="person_address",
    joinColumns=@JoinColumn(name="address_id"
      , referencedColumnName="address_id", unique=true),
    inverseJoinColumns=@JoinColumn(name="person_id"
      , referencedColumnName="person_id" , unique=true)
  )
  private Person person;

组件属性包含的关联实体

PersonL里面包含组件Address,Address跟School是1-N的关系。

@Entity
@Table(name="person_inf")
public class Person
{
  @Id @Column(name="person_id")
  @GeneratedValue(strategy=GenerationType.IDENTITY)
  private Integer id;
  private Address address;
}

@Embeddable
public class Address
{
  @Column(name="address_detail")
  private String addressDetail;
  @Parent
  private Person person;
  @OneToMany(targetEntity=School.class)
  @JoinColumn(name="address_id", referencedColumnName="person_id")
  private Set<School> schools
    = new HashSet<>();
}

@Entity
@Table(name="school_inf")
public class School
{
 @Id @Column(name="school_id")
  @GeneratedValue(strategy=GenerationType.IDENTITY)
  private Integer id;

基于复合主键的关联关系

不推荐使用。总是建议使用没有物理意义的逻辑主键。
对于1-N的双向关联,1的一端将两个属性结合起来作为复合主键。N的一端仍然使用Integer类型的普通主键。
person(1)->address(n)

  @Id
  private String first;
  @Id
  private String last;
  @OneToMany(targetEntity=Address.class, mappedBy="person"
    , cascade=CascadeType.ALL)
  private Set<Address> addresses
    = new HashSet<>();

public class Address{
@ManyToOne(targetEntity=Person.class)
  @JoinColumns({
    @JoinColumn(name="person_first"
      , referencedColumnName="first" , nullable=false),
    @JoinColumn(name="person_last"
      , referencedColumnName="last" , nullable=false)
  })
  private Person person;
  }

hibernate的继承映射

例子:现在有四个类:Person,Employee,Manager,Customer.四个持久化类,其中person还有一个Address组件。
person派生出了employee和customer,employee又派生出了manager.
1. 整个类层次对应一个表(默认)
所有类的属性都放在一个表中。并使用一个列来辨别一条记录到底是属于哪个类的实例。俗称辨别者列(discriminator)。

@Entity
@DiscriminatorColumn(name="person_type" ,
  discriminatorType=DiscriminatorType.STRING)
@DiscriminatorValue("普通人")
@Table(name="person_inf")
public class Person
{

  @Id @Column(name="person_id")
  @GeneratedValue(strategy=GenerationType.IDENTITY)
  private Integer id;
  private String name;
  private char gender;

  @AttributeOverrides({
    @AttributeOverride(name="detail",
    column=@Column(name="address_detail")),
    @AttributeOverride(name="zip",
    column=@Column(name="address_zip")),
    @AttributeOverride(name="country",
    column=@Column(name="address_country"))
  })
  private Address address;

  }

  @Entity
@DiscriminatorValue("员工")
@Table(name="employee_inf")
public class Employee extends Person
{

  private String title;

  private double salary;

  @OneToMany(cascade=CascadeType.ALL
    , mappedBy="employee" , targetEntity=Customer.class)
  private Set<Customer> customers
    = new HashSet<Customer>();

  @ManyToOne(cascade=CascadeType.ALL
    ,targetEntity=Manager.class)
  @JoinColumn(name="manager_id", nullable=true)
  private Manager manager;
  }

@Entity
@DiscriminatorValue("经理")
@Table(name="manager_inf")
public class  Manager extends Employee
{

  private String department;
  @OneToMany(cascade=CascadeType.ALL
    , mappedBy="manager" , targetEntity=Employee.class)
  private Set<Employee> employees
    = new HashSet<Employee>();

2.连接子类的映射策略
父类保存在父类表中,子类由父类表和子类表共同保存。
在继承树的根类中,使用@Inheritance指定映射策略。
@InheritanceType.SINGLE_TABLE:整个类层次一个表
@InheritanceType.JOINED:连接子类
@InheritanceType.TABLE_PER_CLASS:每个类对应一个表。
这种策略无需指定辨别者列。

@Entity
@Inheritance(strategy=InheritanceType.JOINED)
@Table(name="person_inf")
public class Person
{
  // ±êʶÊôÐÔ
  @Id @Column(name="person_id")
  @GeneratedValue(strategy=GenerationType.IDENTITY)
  private Integer id;

  }

 @Entity
@Table(name="employee_inf")
public class Employee extends Person
{
  private String title;
  private double salary;
  @OneToMany(cascade=CascadeType.ALL
    , mappedBy="employee" , targetEntity=Customer.class)
  private Set<Customer> customers
    = new HashSet<>();
  @ManyToOne(cascade=CascadeType.ALL
    ,targetEntity=Manager.class)
  @JoinColumn(name="manager_id", nullable=true)
  private Manager manager;
  }

3.每个类一个表
不能使用@GenerationType.IDENTIFIED,@GenerationType.AUTO指定主键生成策略。

@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
@Table(name="person_inf")
public class Person
{
  @Id @Column(name="person_id")
  @GenericGenerator(name="person_hilo" , strategy="hilo")
  @GeneratedValue(generator="person_hilo")
  private Integer id;
  }

@Entity
@Table(name="employee_inf")
public class Employee extends Person
{
  private String title;
  private double salary;
  @OneToMany(cascade=CascadeType.ALL
    , mappedBy="employee" , targetEntity=Customer.class)
  private Set<Customer> customers
    = new HashSet<>();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值